web-dev-qa-db-fra.com

Combinez deux tables sans champs communs

Je veux apprendre à combiner deux tables de base de données qui n'ont pas de champs en commun. J'ai vérifié UNION mais MSDN a déclaré:

Les règles de base suivantes permettent de combiner les ensembles de résultats de deux requêtes à l’aide de UNION:

  1. Le nombre et l'ordre des colonnes doivent être les mêmes dans toutes les requêtes.
  2. Les types de données doivent être compatibles.

Mais je n'ai aucun champ en commun. Tout ce que je veux, c'est les combiner dans une seule table comme une vue.

Donc qu'est ce que je devrais faire ?

Merci d'avance.

Cordialement. 

49
Tarik

Il y a plusieurs façons de le faire, selon ce que vous vraiment voulez. En l'absence de colonnes communes, vous devez décider si vous souhaitez introduire une colonne commune ou obtenir le produit.

Disons que vous avez les deux tables:

parts:              custs:
+----+----------+   +-----+------+
| id | desc     |   |  id | name |
+----+----------+   +-----+------+
|  1 | Sprocket |   | 100 | Bob  |
|  2 | Flange   |   | 101 | Paul |
+----+----------+   +-----+------+

Oubliez les colonnes car vous auriez très probablement eu une relation client/commande/pièce dans ce cas; Je viens d'utiliser ces colonnes pour illustrer les moyens de le faire.

Un produit cartésien correspondra à chaque ligne du premier tableau et à chaque ligne du second:

> select * from parts, custs;
      id desc     id  name
      -- ----     --- ----
      1  Sprocket 101 Bob
      1  Sprocket 102 Paul
      2  Flange   101 Bob
      2  Flange   102 Paul

Ce n'est probablement pas ce que vous voulez, car 1 000 pièces et 100 clients génèrent 100 000 lignes avec beaucoup d'informations dupliquées.

Vous pouvez également utiliser une union pour produire les données, mais pas côte à côte (vous devez vous assurer que les types de colonne sont compatibles entre les deux sélections, soit en rendant les colonnes de la table compatibles, soit en les contraignant ):

> select id as pid, desc, '' as cid, '' as name from parts
  union
  select '' as pid, '' as desc, id as cid, name from custs;
    pid desc     cid name
    --- ----     --- ----
                 101 Bob 
                 102 Paul
    1   Sprocket
    2   Flange

Dans certaines bases de données, vous pouvez utiliser une colonne ou une pseudo-colonne rowid/rownum pour faire correspondre des enregistrements côte à côte, tels que:

id desc     id  name
-- ----     --- ----
1  Sprocket 101 Bob
2  Flange   101 Bob

Le code serait quelque chose comme:

select a.id, a.desc, b.id, b.name
from parts a, custs b
where a.rownum = b.rownum;

C'est toujours like un produit cartésien mais la clause where limite la façon dont les lignes sont combinées pour former les résultats (donc pas vraiment un produit cartésien).

Je n'ai pas testé ce SQL pour cela car c'est l'une des limites de mon SGBD de choix, et à juste titre, je ne crois pas que cela soit nécessaire dans un schéma correctement pensé. SQL ne garantissant pas l'ordre dans lequel les données sont produites, la correspondance peut changer chaque fois que vous exécutez la requête, à moins que vous n'ayez une relation spécifique ou une clause order by.

Je pense que l’idéal serait d’ajouter une colonne aux deux tableaux précisant la nature de la relation. S'il n'y a pas de relation réelle, vous n'avez probablement pas à vous soucier de les mettre côte à côte avec SQL.

Si vous souhaitez simplement les afficher côte à côte dans un rapport ou sur une page Web (deux exemples), le meilleur outil à utiliser est le type de rapport qui génère votre rapport ou votre page Web, associé à deux requêtes SQL independent à obtenir les deux tables non liées. Par exemple, une grille à deux colonnes dans BIRT (ou Crystal ou Jasper) avec chacune un tableau de données séparé, ou un tableau HTML à deux colonnes (ou CSS) avec chacune un tableau de données séparé.

106
paxdiablo

C'est une demande très étrange, et presque certainement quelque chose que vous ne voudriez jamais faire dans une application du monde réel, mais d'un point de vue purement académique, c'est un défi intéressant. Avec SQL Server 2005, vous pouvez utiliser des expressions de table communes et les fonctions row_number () et rejoindre cette opération:

with OrderedFoos as (
    select row_number() over (order by FooName) RowNum, *
    from Foos (nolock)
),
OrderedBars as (
    select row_number() over (order by BarName) RowNum, *
    from Bars (nolock)
)
select * 
from OrderedFoos f
    full outer join OrderedBars u on u.RowNum = f.RowNum

Cela fonctionne, mais c’est extrêmement ridicule et je ne l’offre que comme réponse à un "wiki de communauté" car je ne le recommanderais vraiment pas.

21
Matt Hamilton
SELECT *
FROM table1, table2

Cela joindra chaque ligne de table1 à table2 (le produit cartésien) renvoyant toutes les colonnes.

11
James Kolpack

Si les tables n'ont pas de champs communs, il est impossible de combiner les données dans une vue significative. Il est plus probable que vous vous retrouviez avec une vue contenant des données dupliquées provenant des deux tables.

3
Craig T

pourquoi n'utilisez-vous pas une approche simple

    SELECT distinct *
    FROM 
    SUPPLIER full join 
    CUSTOMER on (
        CUSTOMER.OID = SUPPLIER.OID
    )

Il vous donne toutes les colonnes des deux tables et renvoie tous les enregistrements du client et du fournisseur si le client a 3 enregistrements et que le fournisseur en a 2, puis le fournisseur affichera NULL dans toutes les colonnes 

2
dnxit

Pour obtenir une vue significative/utile des deux tables, vous devez normalement déterminer un champ d'identification à partir de chaque table, qui peut ensuite être utilisé dans la clause ON dans une JOIN. 

Alors à votre avis:

SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2

Vous indiquez qu'aucun champ n'est «commun», mais bien que les champs d'identification puissent ne pas avoir le même nom ni même le même type de données, vous pouvez utiliser les fonctions convert/cast pour les associer d'une manière ou d'une autre.

2
Ash
Select 
DISTINCT  t1.col,t2col
From table1 t1, table2 t2

OR

Select 
DISTINCT  t1.col,t2col
From table1 t1 
cross JOIN  table2 t2

si ses données câlin, il prend longtemps.

2
mad

essayer:

select * from table 1 left join table2 as t on 1 = 1;

Cela apportera toutes les colonnes de la table.

2
Jay Momaya
select 
    status_id, 
    status, 
    null as path, 
    null as Description 
from 
    zmw_t_status

union
select 
    null, 
    null, 
    path as cid, 
    Description from zmw_t_path;
1
Karthick
SELECT t1.col table1col, t2.col table2col
FROM table1 t1 
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y
1
Robby
select * from this_table;

select distinct person from this_table

union select address as location from that_table 

drop wrong_table from this_database;
0
hard_sense

Très difficile quand vous devez faire cela avec trois déclarations choisies

J'ai essayé toutes les techniques proposées là-haut mais c'est en vain

S'il vous plaît voir ci-dessous script. s'il vous plaît des conseils si vous avez une solution alternative

   select distinct x.best_Achiver_ever,y.Today_best_Achiver ,z.Most_Violator from 

    (SELECT  Top(4) ROW_NUMBER() over (order by tl.username)  AS conj, tl. 
     [username] + '-->' + str(count(*)) as best_Achiver_ever 
    FROM[TiketFollowup].[dbo].N_FCR_Tikect_Log_Archive tl
     group by tl.username
     order by count(*) desc) x
      left outer join 

(SELECT 
Top(4) ROW_NUMBER() over (order by tl.username)  as conj, tl.[username] + '-->' + str(count(*)) as Today_best_Achiver
FROM[TiketFollowup].[dbo].[N_FCR_Tikect_Log] tl
where convert(date, tl.stamp, 121) = convert(date,GETDATE(),121)
group by tl.username
order by count(*) desc) y 
on x.conj=y.conj

 left outer join 

(
select  ROW_NUMBER() over (order by count(*)) as conj,username+ '--> ' + str( count(dbo.IsViolated(stamp))) as Most_Violator from N_FCR_Ticket
where dbo.IsViolated(stamp) = 'violated' and  convert(date,stamp, 121) < convert(date,GETDATE(),121)
group by username
order by count(*) desc) z
on x.conj = z.conj
0
Omar Kamel