SQL查询返回列值,其中另一列是每个序列号的最小值

时间:2014-07-24 09:15:35

标签: sql case min

我有一个如下表格,并希望查询给我一个新列:第一个站点。 表:

--------------------------------------------------------------
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部分。有人可以帮忙吗?

3 个答案:

答案 0 :(得分: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 

答案 1 :(得分:0)

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

答案 2 :(得分:0)

这是一个有效的解决方案:

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

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