【问题标题】:SQL query to return a column value where another column is minimum per serial numberSQL查询返回一个列值,其中另一个列是每个序列号的最小值
【发布时间】:2014-09-15 18:30:27
【问题描述】:

我有一个如下表,并希望通过查询为我提供一个新列:第一个站点。 表:

--------------------------------------------------------------
Serial_No | Production_Date |   Production_Site |   First_Site
--------------------------------------------------------------
001       | 11 June 2013    |   SiteA           |   SiteA
--------------------------------------------------------------
001       | 12 June 2013    |   SiteB           |   SiteA
--------------------------------------------------------------
001       | 12 June 2013    |   SiteC           |   SiteA
--------------------------------------------------------------
001       | 10 June 2013    |   SiteA           |   SiteA
--------------------------------------------------------------
002       | 14 July 2013    |   SiteB           |   SiteA
--------------------------------------------------------------
002       | 14 July 2013    |   SiteC           |   SiteA
--------------------------------------------------------------
002       | 9 May 2013      |   SiteA           |   SiteA
--------------------------------------------------------------
003       | 5 June 2013     |   SiteB           |   SiteB
--------------------------------------------------------------
003       | 19 July 2013    |   SiteC           |   SiteB
--------------------------------------------------------------

First_Site 列读取每个序列号,找到该序列号的最早生产日期,并输出对应于最早日期的站点。

我尝试了以下查询,但他们没有给我想要的结果:

SELECT
Case When ( Production_Date ) = ( MIN( Production_Date ) 
OVER (PARTITION BY ( Serial_No)) ) 
Then (Production_Site) Else 'Null') End AS First_Site
FROM Table

这为每个序列号的 Production_Date 最小的行提供了正确的值,但为序列号的其他行提供了空值:

--------------------------------------------------------------
Serial_No | Production_Date |   Production_Site |   First_Site
--------------------------------------------------------------
001       | 11 June 2013    |   SiteA           |   Null
--------------------------------------------------------------
001       | 12 June 2013    |   SiteB           |   Null
--------------------------------------------------------------
001       | 12 June 2013    |   SiteC           |   Null
--------------------------------------------------------------
001       | 10 June 2013    |   SiteA           |   SiteA
--------------------------------------------------------------
002       | 14 July 2013    |   SiteB           |   Null
--------------------------------------------------------------
002       | 14 July 2013    |   SiteC           |   Null
--------------------------------------------------------------
002       | 9 May 2013      |   SiteA           |   SiteA
--------------------------------------------------------------
003       | 5 June 2013     |   SiteB           |   SiteB
--------------------------------------------------------------
003       | 19 July 2013    |   SiteC           |   Null
--------------------------------------------------------------

这不是我想要的。我的猜测是我必须更改案例陈述的 ELSE 部分。有人可以帮忙吗?

【问题讨论】:

  • 您使用的是哪个 DBMS?甲骨文? Postgres?
  • 我正在使用 Oracle DBMS

标签: sql case min


【解决方案1】:

这似乎行得通。

CREATE TABLE #table (Serial_No int, Production_Date datetime, Production_Site varchar(50), First_Site varchar(50))

INSERT INTO #table VALUES(001, '11 June 2013', 'SiteA', 'SiteA')
INSERT INTO #table VALUES(001, '12 June 2013', 'SiteB', 'SiteA')
INSERT INTO #table VALUES(001, '12 June 2013', 'SiteC', 'SiteA')
INSERT INTO #table VALUES(001, '10 June 2013', 'SiteA', 'SiteA')
INSERT INTO #table VALUES(002, '14 July 2013', 'SiteB', 'SiteA')
INSERT INTO #table VALUES(002, '14 July 2013', 'SiteC', 'SiteA')
INSERT INTO #table VALUES(002, '9 May 2013', 'SiteA', 'SiteA')
INSERT INTO #table VALUES(003, '5 June 2013', 'SiteB', 'SiteB')
INSERT INTO #table VALUES(003, '19 July 2013', 'SiteC', 'SiteB')

SELECT 
    main.*
    ,(
        SELECT MIN(Production_Date) 
        FROM #table AS sub 
        WHERE main.Serial_No = sub.Serial_No
    ) AS Earliest_Production_Date
FROM
    #table as main

但我想这看起来更好:

SELECT 
    main.*
    ,MIN(Production_Date) OVER (PARTITION BY Serial_No)
FROM
    #table as main

或者,如果您想从最早的生产中获取更多数据:

WITH cte AS (
    SELECT 
        main.*
        ,MIN(Production_Date) OVER (PARTITION BY Serial_No) AS Earliest_Production_Date
    FROM
        #table as main
)
SELECT
    cte.*
    ,t.First_Site AS Earliest_First_Site
FROM
    cte
    INNER JOIN #table AS t ON 
        t.Serial_No = cte.Serial_No 
        and t.Production_Date = cte.Earliest_Production_Date 

【讨论】:

    【解决方案2】:
    create table First_Site (serial_no varchar(20), production_date varchar(20), production_site varchar(20), first_site varchar(22))
    
    insert into First_Site select '001', '11 June 2013', 'SiteA', 'SiteA'
    insert into First_Site select '001', '12 June 2013', 'SiteB', 'SiteA'
    insert into First_Site select '001', '12 June 2013', 'SiteC', 'SiteA'
    insert into First_Site select '001', '10 June 2013', 'SiteA', 'SiteA'
    insert into First_Site select '002', '14 July 2013', 'SiteB', 'SiteA'
    insert into First_Site select '002', '14 July 2013', 'SiteC', 'SiteA'
    insert into First_Site select '002', '9 May 2013', 'SiteA', 'SiteA'
    insert into First_Site select '003', '5 June 2013', 'SiteB', 'SiteB'
    insert into First_Site select '003', '19 June 2013', 'SiteC', 'SiteB'
    
    SELECT fs.serial_no, fs.production_date, A.dt, fs.production_site, fs.first_site FROM first_site fs
    JOIN 
    (
        SELECT serial_no, MIN(CONVERT(DATETIME, production_date)) dt , first_site
        FROM first_site 
        GROUP BY serial_no, first_site
    )A ON a.dt = fs.production_date 
    AND A.first_site = fs.first_site
    

    【讨论】:

      【解决方案3】:

      这是一个可行的解决方案:

      SELECT main.*, sub.production_site as first_site 
      FROM t main INNER JOIN t sub ON main.serial_no = sub.serial_no
      WHERE NOT EXISTS 
        (select * from t 
         where serial_no = sub.serial_no and production_date < sub.production_date);
      

      http://sqlfiddle.com/#!2/79d962/4

      此代码的唯一问题是,如果您可以在同一日期拥有多个具有相同序列号的站点,您最终将得到两条记录。

      【讨论】:

        猜你喜欢
        • 2014-02-04
        • 2023-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-27
        • 2021-10-24
        • 1970-01-01
        • 2010-11-02
        相关资源
        最近更新 更多