从不同的表中使用不同的WHERE子句选择列

时间:2019-06-17 14:26:54

标签: sql

就像这里要问的许多问题一样,我需要能够使用2个不同的WHERE子句两次选择同一列。不幸的是,存在一个问题,因为我还试图解决另一个常见问题,因为使用WHERE子句,即使使用LEFT JOIN时,使用COUNT()时也无法显示所有单元格。

所以有两个问题。首先,尽管有LEFT JOIN,WHERE子句仍删除存在NULL的选项之一。

第二,由于WHERE子句,我无法将2个查询合并为一个。

我尝试在内部和外部,子查询,OUTER APPLY和UNION中使用COUNT()的'CASE WHEN'。他们都不显示我的需求。

所以我的第一张桌子显示了学生及其学校的房子:

Table - Houses

StudentID | House
---------------------
    1     |  A
    2     |  B
    3     |  C
    4     |  D
    5     |  A
    6     |  B
    7     |  C
    8     |  D

第二张表显示了房屋得分:

Table - Points
StudentID | House | PointAwardedDate
------------------|-------------------
    1     |  A    |      01/04/2019 10:04:00
    1     |  A    |      17/05/2019 11:25:00
    1     |  A    |      17/06/2019 12:58:00
    2     |  B    |      02/02/2019 08:54:00
    3     |  C    |      03/03/2019 15:46:00
    4     |  D    |      17/06/2019 13:14:00
    5     |  A    |      05/06/2019 15:34:00
    6     |  B    |      01/02/2019 12:32:00
    7     |  C    |      17/06/2019 11:57:00
    8     |  D    |      15/04/2019 09:24:00
    8     |  D    |      17/06/2019 09:45:00

使用以下代码,我可以挑选自上个星期日(2019年6月16日)以来授予的奖项,并显示每所房屋获得了多少奖励:

SELECT
Houses.House,
COUNT(Points.StudentID) AS PointsCount
FROM Houses
LEFT JOIN Points
ON Houses.STudentID = Points.StudentID
WHERE Points.PointsAwardedDate >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY Houses.House

哪个节目

House  |  PointsCount
-------|--------------
  A    |      1
  C    |      1
  D    |      2

问题1:我需要这样显示该表:

House  |  PointsCount
-------|--------------
  A    |      1
  B    |      0
  C    |      1
  D    |      2

问题2-我们需要显示另一列,列出整个学年的分数。因此,我们拥有的(有效的)代码是:

SELECT DISTINCT
    Houses.House,
COUNT(Points.StudentID) AS PointsCountYear
FROM Houses
LEFT JOIN Points
ON Houses.STudentID = Points.StudentID
WHERE Points.PointsAwardedDate >= (
    SELECT 
        TOP 1 Points.PointsAwardedDate
    FROM TblSchoolManagementTermDates
    WHERE Points.PointsAwardedDate <= 
        CONVERT(datetime, GETDATE())
            AND intTerm = 1
        ORDER BY intSchoolYear DESC)
AND txtDate <= (
    SELECT TOP 1 txtFinishDate
    FROM TblSchoolManagementTermDates
    WHERE txtFinishDate >= 
        CONVERT(datetime, GETDATE())
        ORDER BY intSchoolYear ASC)
GROUP BY Pups.txtAcademicHouse

此处的学期日期为2018年9月1日至2019年8月31日

这将拔出下表:

House  |  PointsCountYear
-------|-----------------
  A    |      4
  B    |      2
  C    |      2
  D    |      3

我们需要能够将2组合在一起,因此我们的决赛桌看起来像这样:

House  |  PointsCount |  PointsCountYear
-------|--------------|-----------------
  A    |      1       |      4
  B    |      0       |      2
  C    |      1       |      2
  D    |      2       |      3

我们了解到,第一部分的问题在于WHERE子句正在过滤出房屋B的任何数据,因此即使使用LEFT JOIN也不会显示该数据,但是我们不确定如何将其显示在另一位置仍然保留正确数据的方式。

非常感谢您的帮助。

谢谢 罗布

3 个答案:

答案 0 :(得分:1)

我尝试为SQLServer回答: 问题1的可能解决方案:

CREATE TABLE #HOUSES
(
  STUDENT_ID INT NOT NULL
, HOUSE VARCHAR(1) NOT NULL
);

INSERT INTO #HOUSES  VALUES (1, 'A')
, (2, 'B')
, (3, 'C')
, (4, 'D')
, (5, 'A')
, (6, 'B')
, (7, 'C')
, (8, 'D');

CREATE TABLE #POINTS
(
  STUDENT_ID INT NOT NULL
, HOUSE VARCHAR(1) NOT NULL
, POINTAWARDEDDATE DATE NOT NULL
);

INSERT INTO #POINTS  VALUES 
(1, 'A', '01/04/2019 10:04:00'), 
(1, 'A', '17/05/2019 11:25:00'), 
(1, 'A', '17/06/2019 12:58:00'), 
(2, 'B', '02/02/2019 08:54:00'), 
(3, 'C', '03/03/2019 15:46:00'), 
(4, 'D', '17/06/2019 13:14:00'), 
(5, 'A', '05/06/2019 15:34:00'), 
(6, 'B', '01/02/2019 12:32:00'), 
(7, 'C', '17/06/2019 11:57:00'), 
(8, 'D', '15/04/2019 09:24:00'), 
(8, 'D', '17/06/2019 09:45:00')
;

SELECT H.HOUSE
    , COUNT(P.POINTAWARDEDDATE) AS POINTSCOUNT
FROM
(
SELECT HOUSE
FROM #HOUSES
GROUP BY HOUSE) H
LEFT JOIN #POINTS P
ON H.HOUSE = P.HOUSE
AND P.POINTAWARDEDDATE >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY H.HOUSE

结果:

HOUSE, POINTSCOUNT
A   1
B   0
C   1
D   2

答案 1 :(得分:1)

您可以通过条件聚合来做到这一点:

SELECT
  h.House,
  SUM(CASE 
    WHEN p.PointsAwardedDate >= DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6) THEN 1
    ELSE 0
  END)  AS PointsCount,
  SUM(CASE 
    WHEN p.PointsAwardedDate >= '2018-09-01' AND p.PointsAwardedDate < '2019-09-01'  THEN 1
    ELSE 0
  END) AS PointsCountYear
FROM Houses AS h
LEFT JOIN Points AS p
ON h.STudentID = p.StudentID
GROUP BY h.House

请参见demo
结果:

> House | PointsCount | PointsCountYear
> :---- | ----------: | --------------:
> A     |           1 |               4
> B     |           0 |               2
> C     |           1 |               2
> D     |           2 |               3

答案 2 :(得分:0)

尝试

SELECT h.house
    , COUNT(P.PointsAwardedDate) AS POINTSCOUNT
FROM
(
SELECT StudentId,house
FROM HOUSES
) H
LEFT JOIN POINTS P
ON H.[StudentId] = P.StudentId
AND P.[PointsAwardedDate] >= (SELECT DATEADD(wk, DATEDIFF(wk, 6, GETDATE()), 6))
GROUP BY h.house