Resultados da união Selects em SQL Server
-
23-08-2019 - |
Pergunta
É possível consultas união de tabelas ou exibições que não têm qualquer resultado em comum? O que eu estou tentando fazer é combinar dados de diferentes pontos de vista em um resultado. Tenho
select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3
Eu gostaria que o resultado seja a, b, z, c. É aqui que eu usaria selecione a partir de? O que isso parece?
select ? from (
select a,b,null,c from VIEW1, VIEW2 where VIEW1.a = VIEW2.a
UNION
select null,null,z,null from VIEW3)
Estou usando o MS SQL Server e as vistas não têm chaves primárias. Muito obrigado.
Solução
Se entendi sua pergunta, você provavelmente está obtendo resultados como este:
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
.. mas o que você está tentando fazer com que são resultados como este:
a1, b1, z1, c1
a2, b2, z2, c2
a3, b2, z3, c3
Do I compreender o problema corretamente?
Se isto estiver correto, você precisa ter uma maneira de juntar esses subconsultas em conjunto, de modo que você pode dizer SQL que os 1s andam juntos, e os 2 lá juntos, e assim por diante.
Outras dicas
concatena sindicais resultado conjuntos, não combiná-los.
Então, o que você vai começar a partir de sua primeira consulta é a seguinte:
a b (null) c
(null) (null) z (null)
Se você quiser combiná-los, você vai ter que se juntar a eles, e então você precisa ter algo em comum, ou você vai ter que combinar os dados no programa.
Você só tem 1 linha de cada um?
Se sim, então se o padrão acima é sempre vai ser assim, isso iria funcionar:
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
No entanto, se você não sabe se View3.a tem um valor ou View1.a tem um valor, e você quer a partir da primeira consulta se houver um valor de 3, então isso iria funcionar:
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
Mas, e há um grande MAS aqui. Se você tem mais de uma linha em qualquer uma das vistas, você vai acabar com dados que não pertence juntos. Nesse caso, você deve tem algo em comum.
Aqui está o código completo que eu tentei, juntamente com os resultados:
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
Resultado:
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)
Se você adicionar uma única linha para View3, como este:
INSERT INTO View3 (z) VALUES (51)
Em seguida, você poderá obter estes resultados, observe as linhas duplas:
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)
Se eu entender isso: você está tentando 'colapso' seus resultados e se livrar de todos os nulos? Se assim for, nunca vai resultar de view3 correspondem a um resultado de view1 / view2? Se sim, qual é a relação? Se não, o número de resultados pelo menos igualar?
para vários registros, abordagem ROW_NUMBER () funcionou para mim. A abordagem k Select 1 foi devolver um produto cartesiano.
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
Pode ser que você está procurando algo parecido com isto? (Apenas um palpite)
SELECT
VIEW1.a,
VIEW1.b,
(SELECT TOP 1 z FROM VIEW3) AS z,
VIEW2.c
FROM
VIEW1, VIEW2
WHERE
VIEW1.a = VIEW2.a
Os resultados de qualquer SQL SELECT, incluindo uma união, é um conjunto estático de colunas. (Nenhum polimorfismo.)
Mas você não tem que usar todas as colunas em cada linha, você usa valores nulos nas linhas onde a coluna não tem um valor. Sugiro também que você incluir uma linha 'tipo' para que o cliente pode dizer o tipo (e colunas interessantes) para uma determinada linha.
Exemplo:
(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
)
Você realmente quer uma junção cruzada:
select v1.a, v1.b, VIEW3.z, v1.c de (SELECT a, b, c, A PARTIR DE view1, view2 onde VIEW1.a = VIEW2.a) como v1 CROSS JOIN VIEW3