显示列值为空的其他行

时间:2019-01-03 02:59:51

标签: sql sql-server

我具有以下表格结构

+-----+------+-----+------------+-------+
| sch | clas | std |    date    | count |
+-----+------+-----+------------+-------+
| A   | a1   | Ax  | 31 nov2018 |     2 |
| A   | a1   | Bo  | 1-Dec-19   |     7 |
| A   | b1   | Ax  | 3-Oct-19   |     3 |
| A   | b1   | Ct  | 2-Dec-10   |     2 |
+-----+------+-----+------------+-------+

我需要在下面显示一行

+-----+------+-----+------------+-------+
| sch | clas | std |    date    | count |
+-----+------+-----+------------+-------+
| A   | a1   | Ax  | 31 nov2018 | 2     |
| A   | a1   | Bo  | 1-Dec-19   | 7     |
| A   | a1   | Ct  | null       | null  |
| A   | b1   | Ax  | 3-Oct-19   | 3     |
| A   | b1   | Bo  | null       | null  |
| A   | b1   | Ct  | 2-Dec-10   | 2     |
+-----+------+-----+------------+-------+

列“ std”具有所有类的通用值,即。 Ax,Bo和Ct。 如果这些不可用,则需要显示具有空值的日期和计数行。 在PLSQL中,它很容易实现,但是在这里,我需要在SQL或sql服务器或Postgresql中进行。

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

您可以使用cross join生成行,然后使用left join引入值。

据我了解:

select t.sch, t.clas, v.std, t.date, t.cnt
from (select distinct sch, clas from t) sc cross join
     (values ('Ax'), ('Bo'), ('Ct')) v(std) left join
     t
     on t.sch = sc.sch and t.clas = sc.clas and t.std = v.std
order by t.sch, t.clas, v.std; 

答案 1 :(得分:2)

假设您的表称为数据,那么此

  • 从表(c)中获取学校列表-班级
  • 从表中获取std列表
  • cross加入他们以获得所有可能的组合
  • left将其连接到原始数据

如果您还有其他带有有效的school / class / std数据的表,那么从它们那里获取数据可能会更好,因为这对于Data表中不存在的任何值都不起作用。至少一次。

Select cs.sch, cs.cls, cs.std, d.date, d.count
From 
(
   Select c.sch, c.cls, s.std
   From (Select distinct sch, cls from Data) c  --List of school/classes
   Cross Join (select distinct std from Data) s --list of std
) cs  --every possible combination of school/classes and std
left outer join Data D on D.sch = cs.sch and D.cls = cs.cls and D.std = cs.std  --try and join to the original data

答案 2 :(得分:1)

我们可以在此处使用日历表来生成丢失的数据。然后,左联接到您的表。

WITH sch AS (
    SELECT 'A' AS sch
),
clas AS (
    SELECT 'a1' AS clas UNION ALL
    SELECT 'b1'
),
std AS (
    SELECT 'Ax' AS std UNION ALL
    SELECT 'Bo' UNION ALL
    SELECT 'Ct'
)

SELECT
    s.sch,
    c.clas,
    st.std,
    t.date,
    t.count
FROM sch s
CROSS JOIN clas c
CROSS JOIN std st
LEFT JOIN yourTable t
    ON t.sch = s.sch AND t.clas = c.clas AND t.std = st.std
ORDER BY
    s.sch,
    c.clas,
    st.std;

答案 3 :(得分:1)

-- Edited:如果将需求从INSERT行到表更改为SHOW表的结果,则可以使用以下方法:

WITH std_table AS
(
    SELECT 'Ax' AS std UNION ALL
    SELECT 'Bo' UNION ALL
    SELECT 'Ct' 
)
, tmp_table AS 
(
    SELECT t.sch, t.clas, s.std 
    FROM (SELECT DISTINCT sch, clas FROM table_name) t
    CROSS JOIN std_table s
)
SELECT t.sch, t.clas, t.std, t1.date, t1.count
FROM tmp_table t
LEFT JOIN table_name t1
ON t.sch = t1.sch AND t.clas = t1.clas AND t.std = t1.std
ORDER BY t.sch, t.clas, t.std;

-- End edited

您可以使用此方法,假设表的名称为table_name

WITH std_table AS
(
    SELECT 'Ax' AS std UNION ALL
    SELECT 'Bo' UNION ALL
    SELECT 'Ct' 
)
, tmp_table AS 
(
    SELECT t.sch, t.clas, s.std 
    FROM (SELECT DISTINCT sch, clas FROM table_name) t
    CROSS JOIN std_table s
)
INSERT INTO table_name (sch, clas, std)
SELECT t.sch, t.clas, t.std
FROM tmp_table t
LEFT JOIN table_name t1
ON t.sch = t1.sch AND t.clas = t1.clas AND t.std = t1.std
WHERE t1.std IS NULL;