是否可以有多个带有条件的String_Agg列

时间:2019-01-29 23:15:41

标签: sql sql-server tsql string-aggregation

我有下表的事件注册。在该表中,多日事件被记录为每个注册日期的单独记录。此外,如果日期已满,则仍可以将该日期注册为“等待清单的日期”。我正在尝试根据下表中的日期(字符串汇总日期)中的记录创建一条记录。如下所示的表以及一些相关的表比这要复杂得多,但是为了示例起见我简化了。

EventAssignments表

+--------+---------+----------+--------+------------+
| UserID | EventID | AssignID | DateID | WaitListed |
+--------+---------+----------+--------+------------+
|      1 |      19 |       14 |     67 |          0 |
|      1 |      19 |       14 |     68 |          0 |
|      1 |      19 |       14 |     69 |          1 |
+--------+---------+----------+--------+------------+ 

EventDates表

+--------+-------------------------+---------+------------+
| DateID |        EventDate        | EventID | DateTypeID |
+--------+-------------------------+---------+------------+
|     65 | 2019-03-20 00:00:00.000 |      19 |          1 |
|     66 | 2019-03-21 00:00:00.000 |      19 |          1 |
|     67 | 2019-03-22 00:00:00.000 |      19 |          2 |
|     68 | 2019-03-23 00:00:00.000 |      19 |          2 |
|     69 | 2019-03-24 00:00:00.000 |      19 |          2 |
|     70 | 2019-03-25 00:00:00.000 |      19 |          3 |
+--------+-------------------------+---------+------------+

所需的查询结果应如下所示:

+--------+---------+----------+----------------------------+---------------+
| UserID | EventID | AssignID |      RegisteredDates       | WaitListDates |
+--------+---------+----------+----------------------------+---------------+
|      1 |      19 |       14 | 03/22/2019<br />03/23/2019 | 03/24/2019    |
+--------+---------+----------+----------------------------+---------------+

我当时想我需要一些逻辑,所以我尝试实现CASE的使用,如下所示。但是结果仍然显示为两个记录。第一个记录为常规日期,第二个记录为等待日期

SELECT a.UserID, a.EventID, a.AssignID, 
(CASE WHEN a.WaitListed = 'false' 
    THEN STRING_AGG(CONVERT(varchar, d.EventDate, 101), '<br />') END) AS RegDates, 
(CASE WHEN a.WaitListed = 'true' 
    THEN STRING_AGG(CONVERT(varchar, d.EventDate, 101), '<br />') END) AS WaitListDates
FROM dbo.EventAssignments AS a 
INNER JOIN dbo.EventDates AS d ON a.DateID = d.DateID
GROUP BY a.UserID, a.EventID, a.WaitListed, a.AssignID

2 个答案:

答案 0 :(得分:1)

尝试此查询:

SELECT a.UserID, 
       a.EventID, 
       a.AssignID, 
STRING_AGG(CASE WHEN a.WaitListed = 'false' 
    THEN CONVERT(varchar, d.EventDate, 101) END, '<br />') AS RegDates, 
STRING_AGG(CASE WHEN a.WaitListed = 'true' 
    THEN CONVERT(varchar, d.EventDate, 101) END, '<br />') AS WaitListDates
FROM dbo.EventAssignments AS a 
INNER JOIN dbo.EventDates AS d 
  ON a.DateID = d.DateID
GROUP BY a.UserID, a.EventID, a.AssignID

结果:

UserID  EventID AssignID    RegDates                    WaitListDates
1       19      14          03/22/2019<br />03/23/2019  03/24/2019

答案 1 :(得分:0)

我的错是在结果中缺少连续的<br />

您可以使用递归CTE尝试这种方法吗?
它可能需要替换concat运算符以及ISNULL,但我不太确定您的DBMS ...

WITH OrderedDates AS (
SELECT a.UserID, a.EventID, a.AssignID, a.WaitListed, CONVERT(varchar, d.EventDate, 101)                AS strEventDate,
    ROW_NUMBER() OVER (Partition BY a.UserID, a.EventID, a.AssignID, a.WaitListed ORDER BY d.EventDate) AS EventDateOrder,
    COUNT(*)     OVER (Partition BY a.UserID, a.EventID, a.AssignID, a.WaitListed)                      AS EventDateCount
FROM EventAssignments AS a 
INNER JOIN EventDates AS d ON a.DateID = d.DateID
), ConcatDates AS (
    SELECT UserID, EventID, AssignID, WaitListed, EventDateOrder, EventDateCount, strEventDate
    FROM OrderedDates
    WHERE EventDateOrder = 1
    UNION ALL
    SELECT OD.UserID, OD.EventID, OD.AssignID, OD.WaitListed, OD.EventDateOrder, OD.EventDateCount, CD.strEventDate + '<br />' + OD.strEventDate
    FROM OrderedDates OD
    JOIN ConcatDates CD on OD.UserID = CD.UserID AND OD.EventID = CD.EventID AND OD.AssignID = CD.AssignID AND OD.WaitListed = CD.WaitListed AND OD.EventDateOrder = CD.EventDateOrder + 1
)
SELECT ISNULL(CD1.UserID, CD2.UserID), ISNULL(CD1.EventID, CD2.EventID), ISNULL(CD1.AssignID, CD2.AssignID), CD1.strEventDate, CD2.strEventDate
FROM            (SELECT * FROM ConcatDates WHERE EventDateCOunt = EventDateOrder AND WaitListed = 'false') CD1
FULL OUTER JOIN (SELECT * FROM ConcatDates WHERE EventDateCOunt = EventDateOrder AND WaitListed = 'true' ) CD2 ON CD1.UserID = CD2.UserID AND CD1.EventID = CD2.EventID AND CD1.AssignID = CD2.AssignID