0

我正在構建一個Common Table Expression (CTE)SQL Server 2008用於PIVOT查詢。如何正確使用兩端的數值對varchar字符串進行排序?

我很難正確排序輸出,因爲有數字值將字符串數據夾在中間。是否有可能做到這一點?

這是一個快速和骯髒的例子,真正的查詢將跨越幾年值的價值。

實施例:

Declare @startdate as varchar(max); 
Declare @enddate as varchar(max); 
Set @startdate = cast((DATEPART(yyyy, GetDate())-1) as varchar(4))+'-12-01'; 
Set @enddate = cast((DATEPART(yyyy, GetDate())) as varchar(4))+'-03-15'; 

WITH DateRange(dt) AS 
    (
     SELECT CONVERT(datetime, @startdate) dt 
     UNION ALL 
     SELECT DATEADD(dd,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, @enddate) 
    ) 
    SELECT DISTINCT ',' + QUOTENAME((cast(DATEPART(yyyy, dt) as varchar(4)))+'-Week'+(cast(DATEPART(ww, dt) as varchar(2)))) FROM DateRange 

電流輸出:

,[2012-Week48] 
,[2012-Week49] 
,[2012-Week50] 
,[2012-Week51] 
,[2012-Week52] 
,[2012-Week53] 
,[2013-Week1] 
,[2013-Week10] 
,[2013-Week11] 
,[2013-Week2] 
,[2013-Week3] 
,[2013-Week4] 
,[2013-Week5] 
,[2013-Week6] 
,[2013-Week7] 
,[2013-Week8] 
,[2013-Week9] 

所需的輸出:

,[2012-Week48] 
,[2012-Week49] 
,[2012-Week50] 
,[2012-Week51] 
,[2012-Week52] 
,[2012-Week53] 
,[2013-Week1] 
,[2013-Week2] 
,[2013-Week3] 
,[2013-Week4] 
,[2013-Week5] 
,[2013-Week6] 
,[2013-Week7] 
,[2013-Week8] 
,[2013-Week9] 
,[2013-Week10] 
,[2013-Week11] 

EDIT

當然在我發佈問題後,我的大腦開始工作。我改變了DATEADD添加1周而不是1天,然後在選擇中拿出DISTINCT,它的工作。

DECLARE @startdate AS VARCHAR(MAX); 
DECLARE @enddate AS VARCHAR(MAX); 
SET @startdate = CAST((DATEPART(yyyy, GetDate())-1) AS VARCHAR(4))+'-12-01'; 
SET @enddate = CAST((DATEPART(yyyy, GetDate())) AS VARCHAR(4))+'-03-15'; 

WITH DateRange(dt) AS 
    (
      SELECT CONVERT(datetime, @startdate) dt 
      UNION ALL 
      SELECT DATEADD(ww,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, @enddate) 
    ) 
    SELECT ',' + QUOTENAME((CAST(DATEPART(yyyy, dt) AS VARCHAR(4)))+'-Week'+(CAST(DATEPART(ww, dt) AS VARCHAR(2)))) FROM DateRange 
+1

看起來像一個壞方法。您從字符串開始,將它們投射到日期時間,運行查詢,然後轉換回字符串。爲什麼不從datedate開始,運行查詢並輸出格式化的日期,但是按實際日期排序? –

+0

由於數據透視表Im使用實際存儲日期,但是以修改後的Julian格式存儲。我需要按周來創建數據透視圖,這些數據將跨越多年。這只是整體解決方案的第一個季度,但這正是我需要的。我並不過分關注表現,因爲這將每月運行一次,並在合理的時間內完成。可能有更好的方法來做到這一點,但這是我現在的解決方案。 – ProfessionalAmateur

回答

0

我需要改變查詢的DATEADD部分取出DISTINCT。一旦更改了訂單就可以自行排序

DECLARE @startdate AS VARCHAR(MAX); 
DECLARE @enddate AS VARCHAR(MAX); 
SET @startdate = CAST((DATEPART(yyyy, GetDate())-1) AS VARCHAR(4))+'-12-01'; 
SET @enddate = CAST((DATEPART(yyyy, GetDate())) AS VARCHAR(4))+'-03-15'; 

WITH DateRange(dt) AS 
    (
      SELECT CONVERT(datetime, @startdate) dt 
      UNION ALL 
      SELECT DATEADD(ww,1,dt) dt FROM DateRange WHERE dt < CONVERT(datetime, @enddate) 
    ) 
    SELECT ',' + QUOTENAME((CAST(DATEPART(yyyy, dt) AS VARCHAR(4)))+'-Week'+(CAST(DATEPART(ww, dt) AS VARCHAR(2)))) FROM DateRange 
1

我看不到示例SQL代碼(該網站被列入黑名單,我在哪裏)。

下面是正確的順序排序的數據一招是使用長度,然後再值:

select col 
from t 
order by left(col, 6), len(col), col; 
+0

這種方法的問題是年份可能不同,但長度相同。雖然我喜歡這個概念。 – sgeddes

+0

@sgeddes。 。 。咄。你是對的。這原本是把所有的一週都放在一起,不分年份。我通過只取得字符串的前6個字符來解決這個問題。 –

0

我喜歡戈登的答案,但如果你是死心塌地的文本操作您的訂單通過:

ORDER BY  CAST(REPLACE(LEFT('[2012-Week48]',5),'[','')AS INT) 
      ,CAST(REPLACE(RIGHT('[2012-Week48]',CHARINDEX('Week','[2012-Week48]')-4),']','') AS INT) 
1

你有沒有考慮到排序兩個臨時列(一年SMALLINT和周TINYINT以節省空間......或者直接使用日期部分整數如果空間不是你一個問題,你喜歡快運行)以及使用「按年,按周排序」?

如果您存儲使用更合適的類型(是我的建議)日期,這將進而成爲:

WITH [Define the CTE expression name and column list] 
AS 
    (
    SELECT CAST(DATEPART(yyyy, dt) as smallint(4)) year, cast(DATEPART(ww, dt) as tinyint(2)) week, [your columns here] 
    FROM DateRange WHERE dt < @enddate 
) 
[Define the outer query referencing the CTE name] 
ORDER BY year, week; 
GO 

而且,請注意,字符串操作會減慢你的查詢,以避免他們在可能的情況!

0

這裏是另一個選項,將列的開始和結束部分轉換爲整數。

SELECT * 
FROM YourTable 
ORDER BY CAST(SUBSTRING(yourcolumn,1,4) as int), 
    CAST(SUBSTRING(yourcolumn,CHARINDEX('Week',yourcolumn)+4,len(yourcolumn)) as int) 

這將工作假設數據的格式總是相同的。

0

由於您使用dt生成的字符串,應排序使用日期的部分:

WITH DateRange(dt) ... 
SELECT DISTINCT ',' + QUOTENAM... 
ORDER BY DATEPART(yyyy, dt), DATEPART(ww, dt) 
+0

它沒有這樣做,因爲我沒有在SELECT中選擇yyyy和ww,並且它包含DISTINCT。我確實修復了它,貼在上面。 – ProfessionalAmateur

相關問題