簡體   English   中英

在單個SQL SELECT語句中區分兩行

[英]Difference two rows in a single SQL SELECT statement

我有一個數據庫表,其結構如下所示:

CREATE TABLE dated_records (
              recdate DATE NOT NULL
              col1    DOUBLE NOT NULL,
              col2    DOUBLE NOT NULL,
              col3    DOUBLE NOT NULL,
              col4    DOUBLE NOT NULL,
              col5    DOUBLE NOT NULL,
              col6    DOUBLE NOT NULL,
              col7    DOUBLE NOT NULL,
              col8    DOUBLE NOT NULL
              );

我想寫一個SQL語句,它允許我返回一個包含兩個提供日期之間的變化的記錄,用於指定的列 - 例如col1,col2和col3

例如,如果我想查看col1,col2和col3中的值在兩個日期之間的間隔期間發生了多少變化。 這樣做的一種愚蠢方法是為每個日期選擇行(單獨),然后區分數據庫服務器外的字段 -

SQL1 = "SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-01-01'";
SQL1 = "SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-02-01'";

但是,我確信有一種更聰明的方法可以使用純SQL執行差異。 它會涉及使用自聯接(可能還有一個嵌套的子查詢),但我可能會讓事情變得復雜 - 我覺得最好讓這里的SQL專家看看他們如何解決這個問題。最有效的方式。

理想情況下,SQL應該與數據庫無關,但如果它需要綁定到特定的數據庫,那么它必須是PostgreSQL。

只需選擇兩行,將它們連接成一行,然后減去這些值:

select d1.recdate, d2.recdate,
       (d2.col1 - d1.col1) as delta_col1,
       (d2.col2 - d1.col2) as delta_col2,
       ...
from (select *
      from dated_records
      where recdate = <date1>
     ) d1 cross join
     (select *
      from dated_records
      where recdate = <date2>
     ) d2

我想如果你想要做的是獲取與兩個select查詢不相交的結果集行,你可以使用EXCEPT運算符:

EXCEPT運算符返回第一個結果集中但不在第二個結果集中的行。

所以你的兩個查詢將成為一個單獨的查詢,其中except運算符加入它們:

SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-01-01'
EXCEPT
SELECT col1, col2 col3 FROM dated_records WHERE recdate='2001-02-01'
SELECT
COALESCE
(a.col1 -
  (
    SELECT b.col1
    FROM dated_records b
    WHERE b.id = a.id + 1
  ),
a.col1)
FROM dated_records a
WHERE recdate='2001-01-01';

您可以使用窗口函數DISTINCT

SELECT DISTINCT
       first_value(recdate) OVER () AS date1
      ,last_value(recdate)  OVER () AS date2
      ,last_value(col1)     OVER () - first_value(col1) OVER () AS delta1
      ,last_value(col2)     OVER () - first_value(col2) OVER () AS delta2
       ...
FROM   dated_records
WHERE  recdate IN ('2001-01-01', '2001-01-03')

任何兩天。 使用單個索引或表掃描,因此它應該很快。

我沒有訂購窗口,但所有計算使用相同的窗口,因此值是一致的。

該解決方案可以很容易地推廣用於n行之間的計算。 在這種情況下,您可能希望使用Postgres窗口函數庫中的 nth_value()

如果您正在尋找一個簡單的delta,這似乎是一種更快的方法。

SELECT first(col1) - last(col1) AS delta_col1
, first(col2) - last(col2) AS delta_col2
FROM dated_records WHERE recdate IN ('2001-02-01', '2001-01-01')

您可能不知道第一行或第二行是否先出現,但您始終可以將答案包裹在abs(first(col1)-last(col1))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM