Результаты выбора ОБЪЕДИНЕНИЯ в SQL Server
-
23-08-2019 - |
Вопрос
Возможно ли ОБЪЕДИНИТЬ запросы из таблиц или представлений, которые не имеют никакого общего результата?То, что я пытаюсь сделать, это объединить данные из разных представлений в один результат.У меня есть
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 ? 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, и представления не имеют первичных ключей.Большое спасибо.
Решение
Если я понимаю ваш вопрос, вы, вероятно, получаете подобные результаты:
a1, b1, null, c1
a2, b2, null, c2
a3, b2, null, c3
null, null, z1, null
null, null, z2, null
null, null, z3, nul
l
..но то, что вы пытаетесь получить, - это такие результаты, как этот:
a1, b1, z1, c1
a2, b2, z2, c2
a3, b2, z3, c3
Правильно ли я понимаю проблему?
Если это правильно, вам нужно будет найти способ объединить эти подзапросы вместе, чтобы вы могли сообщить SQL, что 1-е идут вместе, и 2-е идут вместе, и так далее.
Другие советы
Объединение объединяет результирующие наборы, оно не объединяет их.
Итак, что вы получите от своего первого запроса, так это:
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)
Если я понимаю это:вы пытаетесь "свернуть" свои результаты и избавиться от всех нулей?Если да, будет ли когда-нибудь результат из view3 соответствовать результату из view1 / view2?Если да, то какова эта взаимосвязь?Если нет, то совпадает ли хотя бы количество результатов?
Для нескольких записей подход 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
Может быть, вы ищете что-то подобное?(просто дикое предположение)
SELECT
VIEW1.a,
VIEW1.b,
(SELECT TOP 1 z FROM VIEW3) AS z,
VIEW2.c
FROM
VIEW1, VIEW2
WHERE
VIEW1.a = VIEW2.a
Результаты любого sql select, включая объединение, представляют собой статический набор столбцов.(Никакого полиморфизма.)
Но вам не обязательно использовать все столбцы в каждой строке, вы используете нулевые значения в строках, где столбец не имеет значения.Я также предлагаю вам включить строку "тип", чтобы клиент мог указать тип (и интересные столбцы) для данной строки.
Пример:
(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
)
Вы действительно хотите перекрестное соединение:
выберите v1.a, v1.b, VIEW3.z, v1.c из (ВЫБЕРИТЕ a, b, c ИЗ VIEW1, VIEW2, где VIEW1.a = VIEW2.a) как v1 ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ ПРОСМОТР3