views:

43

answers:

5

Hi all

I have the following CTE. Its purpose is to provide unique Month/Year pairs. Later code will use the CTE to produce a concatenated string list of the Month/Year pairs.

;WITH tblStoredWillsInPeriod AS
(
    SELECT DISTINCT Kctc.GetMonthAndYearString(DateWillReceived) Month
    FROM Kctc.StoredWills
    WHERE DateWillReceived BETWEEN '2010/01/01' AND '2010/03/31'
    ORDER BY DateWillReceived
)

I have omitted the implmementation of the GetMonthAndYearString function as it is trivial.

Edit: As requested by Martin, here is the surrounding code:

DECLARE @PivotColumnHeaders nvarchar(MAX)
--CTE declaration as above---
SELECT @PivotColumnHeaders =
  COALESCE(
    @PivotColumnHeaders + ',[' + Month + ']',
    '[' + Month + ']'
  )
FROM tblStoredWillsInPeriod
SELECT @PivotColumnHeaders

Sadly, it seems T-SQL is always one step ahead. When I run this code, it tells me I'm not allowed to use ORDER BY in a CTE unless I also use TOP (or FOR XML, whatever that is.) If I use TOP, it tells me I can't use it with DISTINCT. Yup, T-SQL has all the answers.

Can anyone think of a solution to this problem which is quicker than simply slashing my wrists? I understand that death from blood loss can be surprisingly lingering, and I have deadlines to meet.

Thanks for your help.

David

A: 

Could you clarify why you need the data in the the CTE to be ordered? And why you are not able to order the data in the query using the CTE. Remember data in an ordinary subquery can't be ordered either.

openshac
Sure. The list of month/year pairs are to be used in a dynamic pivot query. Look at the final example here: http://www.kodyaz.com/articles/t-sql-pivot-tables-in-sql-server-tutorial-with-examples.aspx.I'm not able to order the data in the query using the CTE because T-SQL tells me I'm not able to! I just can't use the ORDER BY clause.
David
A: 

What about?

;WITH tblStoredWillsInPeriod AS 
( 
    SELECT DISTINCT Kctc.GetMonthAndYearString(DateWillReceived) Month 
    FROM Kctc.StoredWills 
    WHERE DateWillReceived BETWEEN '2010/01/01' AND '2010/03/31' 
    ORDER BY DateWillReceived 
),
tblStoredWillsInPeriodOrdered AS
(
    SELECT TOP 100 PERCENT Month 
    FROM tblStoredWillsInPeriod 
    ORDER BY Month
)
Chris Bednarski
Have you any link that says an ORDER BY in a CTE will always be respected when it comes to SELECT from it? (Thinking of Jeff Moden's statement here http://weblogs.sqlteam.com/mladenp/archive/2009/07/28/SQL-Server-2005-Fast-Running-Totals.aspx)
Martin Smith
Thanks Chris, I see where you are coming from here. I can't order by Month, because it's a varchar field that won't yield a chronological list (e.g. Feb-2010 will come before Jan-2010). But I could construct a composite year/month field in the CTE, then in the following code, sort by it.I will look into this.
David
No, I have no means to use ORDER BY in the following code that I can see...
David
@Martin Smith: LOL, I don't know what I was thinking ... I already knew that results of a CTE (just like a view) are not guaranteed to be returned in any specific order. My solution is totally useless in its current form.
Chris Bednarski
A: 
SELECT DISTINCT TOP 100 PERCENT ...
ORDER BY ...
Anthony Faull
You can't use TOP with DISTINCT...
David
Thanks for the heads up. I had it the wrong way around. I've placed 'DISTINCT' before 'TOP 100 PERCENT' to fix the syntax error.
Anthony Faull
A: 

And you think you know T-SQL syntax!

Turns out I was wrong about not being able to use TOP and DISTINCT together.

This yields a syntax error...

SELECT TOP 100 PERCENT DISTINCT...

whereas this is absolutely fine...

SELECT DISTINCT TOP 100 PERCENT...

Work that one out.

One drawback is that you have to include the ORDER BY field in the SELECT list, which in all likelihood will interfere with your expected DISTINCT results. Sometimes T-SQL has you running around in circles.

But for now, my wrists are left unmarked.

David
Ah, although I've discovered that this isn't syntactically valid, the results aren't actually sorted!!!Anyone else?
David
+1  A: 

Will this work?

DECLARE @PivotColumnHeaders VARCHAR(MAX)

;WITH StoredWills AS
(
SELECT GETDATE() AS DateWillReceived
UNION ALL
SELECT '2010-03-14 11:48:07.580'
UNION ALL
SELECT '2010-03-12 11:48:07.580'
UNION ALL
SELECT '2010-02-12 11:48:07.580'
),
tblStoredWillsInPeriod AS
(
    SELECT DISTINCT STUFF(RIGHT(convert(VARCHAR, DateWillReceived, 106),8), 4, 1, '-') AS  MMMYYYY, 
    DatePart(Year,DateWillReceived) AS  Year,
    DatePart(Month,DateWillReceived) AS  Month
    FROM StoredWills
    WHERE DateWillReceived BETWEEN '2010-01-01' AND '2010-03-31'
)


SELECT @PivotColumnHeaders =
  COALESCE(
    @PivotColumnHeaders + ',[' + MMMYYYY + ']',
    '[' + MMMYYYY + ']'
  )
FROM tblStoredWillsInPeriod
ORDER BY Year, Month
Martin Smith
Ah, so Chris Bednarski's suggestion of leaving the sorting out of the CTE and doing it in the following code was right. I just couldn't work out how to add sorting to the SELECT ... COALESCE bit. Thank you Martin!
David
Could use DATENAME instead of CONVERT. Otherwise, just like a bought one. +1
Chris Bednarski