【问题标题】:Select additional columns for a SELECT MIN() statement为 SELECT MIN() 语句选择其他列
【发布时间】:2013-11-27 15:04:03
【问题描述】:

我有这个当前选择:

  SELECT MIN(CONVERT(DateTime,SUBSTRING(NameAndDate,14,8))),
         SUBSTRING(NameAndDate,1,12)
    FROM MyData
   WHERE pName IN (SELECT SUBSTRING(NameAndDate,1,12)
                     FROM MyData
                 GROUP BY SUBSTRING(NameAndDate,1,12)
                   HAVING COUNT(*) > 1)
GROUP BY SUBSTRING(NameAndDate,1,12)

SUBSTRING(NameAndDate,1,60) 是此人的 ID 名称,SUBSTRING(NameAndDate,61,8) 是他们进来的日期。

这个数据在表格中多次出现,这就是为什么我要选择 MIN 日期。

问题是我需要在表 (ID) 中添加另一列,但我不想按它进行分组,因为它会将重复项添加到 Person 的 ID。

有没有办法可以做到以下几点:

  SELECT ID,
         MIN(CONVERT(DateTime,SUBSTRING(NameAndDate,14,8))),
         SUBSTRING(NameAndDate,1,12)
    FROM MyData
   WHERE pName IN (SELECT SUBSTRING(NameAndDate,1,12)
                     FROM MyData
                 GROUP BY SUBSTRING(NameAndDate,1,12)
                   HAVING COUNT(*) > 1)
GROUP BY SUBSTRING(NameAndDate,1,12)

编辑:

一个人可能经过多次:

 ID | NameAndDate
----+-----------------------
  1 | J60047238486 08162013
  2 | J60047238486 08182013
  3 | J60047238486 08242013
  4 | J60047238486 09032013
  5 | J60047238486 10102013
  6 | C40049872351 05302013
  7 | C40049872351 07212013
  8 | C40049872351 07252013

我当前的选择拉动:

         Name | Date
--------------+---------------------
 J60047238486 | 08/16/2013 00:00:00
 C40049872351 | 05/30/2013 00:00:00

但我想为这些特定行添加 ID 列:

 ID |     Name     | Date
----+--------------+---------------------
  1 | J60047238486 | 08/16/2013 00:00:00
  6 | C40049872351 | 05/30/2013 00:00:00

【问题讨论】:

  • 不,您必须以某种方式聚合它,或者按它分组。为什么 ID 列会破坏您的分组?除非它是某种代理键,在这种情况下,我不明白您为什么要在输出中使用它。
  • 我将在问题中发布一个示例。
  • 您要为每组SUBSTRING(NameAndDate,1,60) 选择哪个ID 值?
  • 添加了一个编辑,希望能把事情弄清楚

标签: sql-server sql-server-2005 select group-by


【解决方案1】:

试试这个

SELECT * FROM (
SELECT id, 
 CONVERT(DateTime,right (SUBSTRING(NameAndDate,14,8),4) 
                            + SUBSTRING(NameAndDate,14,4)) D,

SUBSTRING(NameAndDate,1,12) N,

COUNT(*) OVER (PARTITION BY SUBSTRING(NameAndDate,1,12)) Cnt,

ROW_NUMBER() OVER (PARTITION BY SUBSTRING(NameAndDate,1,12) 
                   ORDER By SUBSTRING(NameAndDate,14,8)) rn
FROM
mydata
) v WHERE CNT > 1 and rn = 1;

SQL DEMO HERE

【讨论】:

  • 这个实际上效果更好。感谢这次更新。
【解决方案2】:

你可以这样做,但它并不漂亮。您必须运行原始查询以获取每个名称的最短日期,然后将其连接回您的 MyData 表。由于您存储数据的方式,它特别难看。将您的 MMDDYYYY 字符串转换为数据真的很有趣。

SQL Fiddle

select
MyData.[ID],
t1.theName,
t1.theDate
from
Mydata
inner join
(
select
SUBSTRING(NameAndDate,1,12) as theName,
min (
convert(datetime,
right (SUBSTRING(NameAndDate,14,8),4) + '-' + 
left (SUBSTRING(NameAndDate,14,8),2) +  '-' + 
SUBSTRING((SUBSTRING(NameAndDate,14,8)),3,2)
))as theDate
from
mydata

where
SUBSTRING(NameAndDate,1,12) in
(SELECT SUBSTRING(NameAndDate,1,12)
                     FROM MyData
                 GROUP BY SUBSTRING(NameAndDate,1,12)
                   HAVING COUNT(*) > 1)

group by
SUBSTRING(NameAndDate,1,12) ) t1
ON SUBSTRING(mydata.NameAndDate,1,12) = t1.theName
AND (convert(datetime,
right (SUBSTRING(NameAndDate,14,8),4) + '-' + 
left (SUBSTRING(NameAndDate,14,8),2) +  '-' + 
SUBSTRING((SUBSTRING(NameAndDate,14,8)),3,2))) = t1.theDate

【讨论】:

  • 其实差很多,我只是把它简化了一点让别人理解。我会试试这个。谢谢!
【解决方案3】:
with cte as (
    -- first cte - parsing data
    select
        ID,
        left(NameAndDate, 12) as Name,
        convert(date,
            right(NameAndDate, 4) + 
            substring(NameAndDate, 14, 2) +
            substring(NameAndDate, 16, 2),
        112) as Date
    from Table1
), cte2 as (
    -- second cte - create row_number  
    select
        ID, Name, Date,
        row_number() over(partition by Name order by Date) as rn
    from cte
)
select
    ID, Name, Date
from cte2
where rn = 1

sql fiddle demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-05
    • 2023-01-28
    • 2019-03-06
    • 1970-01-01
    • 2021-11-17
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多