在 Sqlite 中,为不同列中返回的每个名称获取前 2 个

Posted

技术标签:

【中文标题】在 Sqlite 中,为不同列中返回的每个名称获取前 2 个【英文标题】:In Sqlite get top 2 for each name returned in different columns 【发布时间】:2020-11-14 18:48:16 【问题描述】:

我有这个返回按 Hipaa_Short 分组的最近 2 个日期。对于每个 Hipaa_Short,我想要一个列中的最新消息和另一列中的第二个最新消息。有可能缺少日期(因此 Hipaa_Short 只有一行)在这种情况下,我也希望显示空值。我正在使用 Sqlite3,所以我确信一些“花哨”的东西不会起作用。

SELECT * FROM 
    (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY Hipaa_Short ORDER BY Meeting_Date DESC) AS rn
    FROM Meetings
    )  
WHERE rn < 3

这是我得到的,但不是我想要的:

 pk_id   Hipaa_Short   Meeting_Date     rn
+-------|-------------|--------------+-----+
|   2   |  LastFirst  | 2020-02-01   |  2  |
|   5   |  LastFirst  | 2020-03-01   |  1  |
|   6   |  JoneBob    | 2020-03-01   |  2  |
|   7   |  JoneBob    | 2020-04-01   |  1  |
|   8   |  JonesTom   | 2020-06-01   |  2  |
|   9   |  JonesTom   | 2020-07-01   |  1  |
|   10  |  NortEdw    | 2020-04-01   |  1  |
+-------|-------------|--------------+-----+

会议桌:

REATE TABLE "Meetings" (
    "id_pk" INTEGER NOT NULL,
    "Hipaa_Short"   TEXT NOT NULL,
    "Meeting_Date"  TEXT NOT NULL,
    "MTG_Year"  INTEGER,
    "MTG_Month" INTEGER,
    "MTG_Day"   INTEGER,
    "CN_Date"   TEXT,
    "Meeting_Type"  TEXT,
    "Date_Added"    TEXT,
    "Annual"    TEXT,
    "LOCSI_Flag"    TEXT,
    "Hipaa_RID" TEXT,
    PRIMARY KEY("id_pk"),
    UNIQUE("Hipaa_Short","Meeting_Date")
)

样本数据:

 pk_id   Hipaa_Short   Meeting_Date 
+-------|-------------|--------------+
|   1   |  LastFirst  | 2020-01-01   | 
|   2   |  LastFirst  | 2020-02-01   | 
|   3   |  JoneBob    | 2020-02-01   | 
|   4   |  JonesTom   | 2020-02-01   | 
|   5   |  LastFirst  | 2020-03-01   | 
|   6   |  JoneBob    | 2020-03-01   | 
|   7   |  JoneBob    | 2020-04-01   | 
|   8   |  JonesTom   | 2020-06-01   | 
|   9   |  JonesTom   | 2020-07-01   | 
|   10  |  NortEdw    | 2020-04-01   |  
+-------|-------------|--------------+

期望的输出:

  Hipaa_Short   Prior Date   Next Date  
+-------------|------------+------------+
|  LastFirst  | 2020-02-01 | 2020-03-01 |
|  JoneBob    | 2020-03-01 | 2020-04-01 |
|  JonesTom   | 2020-06-01 | 2020-07-01 |
|  NortEdw    |            | 2020-04-01 |
+-------------|------------|------------+

【问题讨论】:

【参考方案1】:

您可以在现有查询之上使用条件聚合来透视结果集:

select 
    hipaa_short,
    max(case when rn = 2 then meeting_date end) prior_date,
    max(case when rn = 1 then meeting_date end) next_date,
from (
    select 
        m.*, 
        row_number() over (partition by hipaa_short order by meeting_date desc) as rn
    from meetings m
) m
where rn <= 2
group by hipaa_short

【讨论】:

【参考方案2】:

GMB 对这个特定问题的回答略短一点:

select hipaa_short, min(meeting_date) as prior_date, max(meeting_date) as next_date
from (select m.*, 
             row_number() over (partition by hipaa_short order by meeting_date desc) as rn
      from meetings m
     ) m
where rn <= 2
group by hipaa_short

【讨论】:

【参考方案3】:

由于您已经需要对分区进行排序以获得第一个分区,因此使用 lead() 窗口函数可以轻松(并且更有效)将两个日期放在一行中,而无需额外聚合:

WITH cte AS
  (SELECT Hippa_Short
        , lead(Meeting_Date) OVER w AS "Prior Date"
        , Meeting_Date AS "Next Date"
        , row_number() OVER w AS rn
   FROM meetings
   WINDOW w AS (PARTITION BY Hippa_Short ORDER BY Meeting_Date DESC))
SELECT Hippa_Short, "Prior Date", "Next Date"
FROM cte
WHERE rn = 1;

给予

Hippa_Short  Prior Date  Next Date
-----------  ----------  ----------
JoneBob      2020-03-01  2020-04-01
JonesTom     2020-06-01  2020-07-01
LastFirst    2020-02-01  2020-03-01
NortEdw                  2020-04-01

【讨论】:

以上是关于在 Sqlite 中,为不同列中返回的每个名称获取前 2 个的主要内容,如果未能解决你的问题,请参考以下文章

在Laravel中获取具有不同外国ID的列中的最大值

返回在列中具有相同确切项目的不同名称对

如何使用 Linq 获取列中每个不同值的计数

使用sqlite意图后如何从listview中获取项目名称?

Sqlite 从不同的列中减去不同的行

SQLite 替换现有列中的数据