SQL JOIN将列组合到单个列

时间:2012-12-11 11:29:47

标签: sql sql-server-2008 tsql sql-server-2008-r2

我为Microsoft SQL Server 2008 R2编写了以下查询...

with 
downloads as
(
    select convert(varchar(10), timestamp, 112) as downloadDate, COUNT(*) as counter 
    from <download_table> 
    group by convert(varchar(10), timestamp,112)
),
uploads as 
(
    select CONVERT(varchar(10), dateadded, 112) as uploadDate, COUNT(*) as counter
    from <upload_table>
    group by CONVERT(varchar(10), dateadded, 112)
)
select 
    downloads.downloadDate, 
    uploads.uploadDate, 
    downloads.counter as dCount,
    uploads.counter as uCount
from downloads 
full join uploads on uploads.uploadDate = downloads.downloadDate
order by downloadDate desc;

返回下表...

downloadDate    uploadDate  dCount  uCount
20121211    NULL        40  NULL
20121210    NULL        238 NULL
20121207    20121207    526 4
20121206    20121206    217 12
20121205    NULL        108 NULL
20121204    20121204    190 13
20121203    NULL        141 NULL
20121130    20121130    248 187
20121129    NULL        134 NULL
20121128    NULL        102 NULL
20121127    20121127    494 57
20121126    NULL        153 NULL
20121119    20121119    319 20
20121118    NULL        4   NULL
20121116    20121116    215 16
20121112    20121112    431 144
20121109    20121109    168 48
20121108    20121108    132 181
NULL        20121125    NULL    3

但我无法将两个日期合并到一个'date'列而不会获得一些NULL条目,也无法在dCount或uCount中获取NULL值以显示0而不是NULL。

有人可以帮帮我吗?

4 个答案:

答案 0 :(得分:2)

根据您的SQL方言,IFNULL()NVL()COALESCE()IIF()等内容将帮助您摆脱NULL,转而支持日期过去,例如'18000101'。

完成此操作后,您可以使用MAX()SWITCH()IIF()IF()或朋友制作单个“上次使用日期”列。

答案 1 :(得分:2)

在SQL Serve中,您可以在日期字段周围使用COALESCE,该字段返回计数总计周围的第一个非空值和ISNULL,以将null值替换为零:

with 
downloads as
(
    select convert(varchar(10), timestamp, 112) as downloadDate, COUNT(*) as counter 
    from download_table 
    group by convert(varchar(10), timestamp,112)
),
uploads as 
(
    select CONVERT(varchar(10), dateadded, 112) as uploadDate, COUNT(*) as counter
    from upload_table
    group by CONVERT(varchar(10), dateadded, 112)
)
select 
    coalesce(downloads.downloadDate, uploads.uploadDate) as dDate, 
    isnull(downloads.counter, 0) as dCount,
    isnull(uploads.counter, 0) as uCount
from downloads 
full join uploads 
  on uploads.uploadDate = downloads.downloadDate
order by downloadDate desc;

请参阅SQL Fiddle with Demo

结果:

|    DDATE | DCOUNT | UCOUNT |
------------------------------
| 20121211 |      2 |      0 |
| 20121210 |      1 |      1 |
| 20121207 |      1 |      0 |
| 20121206 |      2 |      1 |
| 20121208 |      0 |      1 |
| 20121209 |      0 |      1 |
| 20121204 |      0 |      1 |
| 20121205 |      0 |      1 |

答案 2 :(得分:1)

您可以像这样使用coalesce和nvl:

with 
downloads as
(
    select convert(varchar(10), timestamp, 112) as downloadDate, COUNT(*) as counter 
    from <download_table> 
    group by convert(varchar(10), timestamp,112)
),
uploads as 
(
    select CONVERT(varchar(10), dateadded, 112) as uploadDate, COUNT(*) as counter
    from <upload_table>
    group by CONVERT(varchar(10), dateadded, 112)
)
select 
    coalesce(downloads.downloadDate, uploads.uploadDate) as dDate, 
    nvl(downloads.counter, 0) as dCount,
    nvl(uploads.counter, 0) as uCount
from downloads 
full join uploads on uploads.uploadDate = downloads.downloadDate
order by downloadDate desc;

答案 3 :(得分:1)

首先,如果要在SQL-Server 2008中删除time元素而不是转换为varchar,最好将日期时间转换为日期,只需使用:

CAST(DateAdded AS DATE)

然后我不是使用FULL JOIN,而是使用UNION ALL执行此操作,它应该表现更好(尽管我不能说100%没有测试您的实际数据)。

WITH Data AS
(   SELECT  [Date] = CAST(Timestamp AS DATE),
            [Downloads] = 1,
            [Uploads] = 0
    FROM    Download_Table
    UNION ALL
    SELECT  [Date] = CAST(DateAdded AS DATE),
            [Downloads] = 0,
            [Uploads] = 1
    FROM    Upload_Table
)
SELECT  [Date], 
        [Downloads] = SUM(Downloads),
        [Uploads] = SUM(Uploads)
FROM    Data
GROUP BY [Date]
ORDER BY [Date];