Результаты выбора UNION в SQL Server - PullRequest
1 голос
/ 20 мая 2009

Возможно ли объединение запросов из таблиц или представлений, которые не имеют общего результата? То, что я пытаюсь сделать, это объединить данные из разных представлений в один результат. У меня

select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3

Я бы хотел, чтобы результат был a, b, z, c. Это где я бы использовал выбрать из? Как это выглядит?

select ? from (
select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3)

Я использую MS SQL Server, и у представлений нет первичных ключей. Большое спасибо.

Ответы [ 7 ]

2 голосов
/ 20 мая 2009

Объединение объединяет наборы результатов, но не объединяет их.

Итак, что вы получите от первого запроса:

  a      b    (null)  c
(null) (null)   z    (null)

Если вы хотите объединить их, вам нужно присоединиться к ним, а затем вам нужно что-то общее, или вам придется объединить данные в программе.

У вас есть только 1 ряд от каждого?

Если это так, то если шаблон выше всегда будет таким, это будет работать:

SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
FROM (
    SELECT 1 k, View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
INNER JOIN (
    SELECT 1 k, NULL a, NULL b, z, NULL c
    FROM View3) SQ2 ON SQ1.k = SQ2.k

Однако, если вы не знаете, имеет ли View3.a значение или View1.a имеет значение, и вам нужен один из первого запроса, если есть значение 3, тогда это будет работать:

SELECT COALESCE(SQ1.a, SQ2.a) a, COALESCE(SQ1.b, SQ2.b) b,
    COALESCE(SQ1.z, SQ2.z) z, COALESCE(SQ1.c, SQ2.c) c
FROM (
    SELECT 1 k, View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
INNER JOIN (
    SELECT 1 k, NULL a, NULL b, z, NULL c
    FROM View3) SQ2 ON SQ1.k = SQ2.k

Но и здесь есть большое НО. Если у вас есть несколько строк в любом из представлений, вы получите данные, которые не принадлежат друг другу. В этом случае вы должны иметь что-то общее.

Вот полный код, который я пробовал, вместе с результатами:

USE master
GO

DROP DATABASE TestDB
GO

CREATE DATABASE TestDB
GO

USE TestDB
GO

CREATE TABLE View1
(
    a INT,
    b INT,
    c INT
)
GO

CREATE TABLE View2
(
    a INT,
    z INT
)
GO

CREATE TABLE View3
(
    z INT
)
GO

INSERT INTO View1 (a, b, c) VALUES (10, 20, 30)
GO

INSERT INTO View2 (a, z) VALUES (10, 40)
GO

INSERT INTO View3 (z) VALUES (50)
GO


SELECT View1.a, b, NULL z, c
FROM View1 INNER JOIN View2 ON View1.a = View2.a
UNION
SELECT NULL a, NULL b, z, NULL c
FROM View3

SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
FROM (
    SELECT 1 k, View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
INNER JOIN (
    SELECT 1 k, NULL a, NULL b, z, NULL c
    FROM View3) SQ2 ON SQ1.k = SQ2.k

SELECT COALESCE(SQ1.a, SQ2.a) a, COALESCE(SQ1.b, SQ2.b) b,
    COALESCE(SQ1.z, SQ2.z) z, COALESCE(SQ1.c, SQ2.c) c
FROM (
    SELECT 1 k, View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
INNER JOIN (
    SELECT 1 k, NULL a, NULL b, z, NULL c
    FROM View3) SQ2 ON SQ1.k = SQ2.k

Результаты:

a           b           z           c
----------- ----------- ----------- -----------
NULL        NULL        50          NULL
10          20          NULL        30

(2 row(s) affected)

a           b           z           c
----------- ----------- ----------- -----------
10          20          50          30

(1 row(s) affected)

a           b           z           c
----------- ----------- ----------- -----------
10          20          50          30

(1 row(s) affected)

Если вы добавите одну строку в View3, например:

INSERT INTO View3 (z) VALUES (51)

Тогда вы получите эти результаты, обратите внимание на сдвоенные строки:

a           b           z           c
----------- ----------- ----------- -----------
NULL        NULL        50          NULL
NULL        NULL        51          NULL
10          20          NULL        30

(3 row(s) affected)

a           b           z           c
----------- ----------- ----------- -----------
10          20          50          30
10          20          51          30

(2 row(s) affected)

a           b           z           c
----------- ----------- ----------- -----------
10          20          50          30
10          20          51          30

(2 row(s) affected)
2 голосов
/ 20 мая 2009

Если я понимаю ваш вопрос, вы, вероятно, получите такие результаты:

a1, b1, null, c1
a2, b2, null, c2
a3, b2, null, c3
null, null, z1, null
null, null, z2, null
null, null, z3, nul

л

.. но то, что вы пытаетесь получить, это результаты:

a1, b1, z1, c1
a2, b2, z2, c2
a3, b2, z3, c3

Правильно ли я понимаю проблему?

Если это правильно, у вас должен быть способ объединить эти подзапросы, чтобы вы могли сообщить SQL, что единицы идут вместе, а две - вместе и т. Д.

1 голос
/ 08 октября 2016


Для нескольких записей подход ROW_NUMBER () работал для меня. Подход Select 1 k возвращал декартово произведение.

SELECT SQ1.a, SQ1.b, SQ2.z, SQ1.c
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY a) k, View1.a, b, NULL z, c
    FROM View1 INNER JOIN View2 ON View1.a = View2.a) SQ1
INNER JOIN (
    SELECT ROW_NUMBER() OVER (ORDER BY b) k, NULL a, NULL b, z, NULL c
    FROM View3) SQ2 ON SQ1.k = SQ2.k
1 голос
/ 20 мая 2009

Если я понимаю это: вы пытаетесь «свернуть» свои результаты и избавиться от всех NULL? Если так, будет ли когда-либо результат из view3 соответствовать результату из view1 / view2? Если да, то каковы отношения? Если нет, совпадет ли хотя бы количество результатов?

0 голосов
/ 20 мая 2009

Вы действительно хотите кросс-соединение:

выберите v1.a, v1.b, VIEW3.z, v1.c из (ВЫБЕРИТЕ a, b, c, ОТ VIEW1, VIEW2, где VIEW1.a = VIEW2.a) как v1 CROSS JOIN VIEW3

0 голосов
/ 20 мая 2009

Результаты любого выбора SQL, включая объединение, представляют собой статический набор столбцов. (Без полиморфизма.)

Но вам не нужно использовать все столбцы в каждой строке, вы используете нулевые значения в строках, где столбец не имеет значения. Я также предлагаю вам включить строку 'type', чтобы клиент мог определить тип (и интересные столбцы) для данной строки.

Пример:

 (Select
   'room' as view_type
 , rooms.room as room
 , NULL as color
 From rooms 
 )
UNION ALL
(Select
  'color' as view_type
 , NULL as room
 , colors.color as color
 From colors 
)
0 голосов
/ 20 мая 2009

Может быть, вы ищете что-то подобное? (просто дикая догадка)

SELECT 
  VIEW1.a,
  VIEW1.b,
  (SELECT TOP 1 z FROM VIEW3) AS z,
  VIEW2.c
FROM
  VIEW1, VIEW2 
WHERE
  VIEW1.a = VIEW2.a
...