SELECT MonthName, SUM(ExpenseClaimCount) AS Expr1, 'EXPENSE-CLAIM' AS ROW_TYPE
FROM (SELECT b.OrganisationID, a.ExpenseClaimCount, c.MonthName
FROM Fact.MonthlyFactOrgMap AS a INNER JOIN
Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey INNER JOIN
Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014) AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate) AND (c.MonthName IN ('March', 'April', 'May', 'June')) AND
(a.ExpenseClaimCount > 0)) AS q
GROUP BY MonthName
UNION
SELECT MonthName, SUM(FixedAssetCount) AS Expr1, 'FIXED ASSET' AS ROW_TYPE
FROM (SELECT b.OrganisationID, a.FixedAssetCount, c.MonthName
FROM Fact.MonthlyFactOrgMap AS a INNER JOIN
Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey INNER JOIN
Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014) AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate) AND (c.MonthName IN ('March', 'April', 'May', 'June')) AND
(a.FixedAssetCount > 0)) AS q_2
GROUP BY MonthName
This is the query that I have ...all the suggestions below worked but not with union
试试这个ORDER BY
ORDER BY CHARINDEX(LEFT(MonthName,3),'AprMayJunJulAugSepOctNovDecJanFebMar')
If you need data in a particular order, you should add a group by
clause. In this case, group by monthname
will produce the alphabetical order you do not want. So try this instead:
order by (case when MonthName = 'March' then 3
when MonthName = 'April' then 4
when MonthName = 'May' then 5
when MonthName = 'June' then 6
end)
Depending on the database there are simpler ways of expressing this idea.
EDIT:
Perhaps a better approach is to keep the minimum date for each month and use that for ordering. Also, you don't need the subquery:
SELECT c.MonthName, SUM(a.ExpenseClaimCount) as expr1, 'EXPENSE-CLAIM' AS ROW_TYPE
FROM Fact.MonthlyFactOrgMap AS a
INNER JOIN Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey
INNER JOIN Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014)
AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate)
AND (c.MonthName IN ('March', 'April', 'May', 'June'))
AND (a.ExpenseClaimCount > 0)) AS q
GROUP BY MonthName
ORDER BY MIN(c.FullDate);
You will want to convert the string to a number, which can be done by converting it to a DATE format and then getting the MM datepart from it.
-- the day and year don't matter because we only care about month
DATEPART(MM, CONVERT(DATE, [MonthName] + '01, 2000', 110))
So your query would look something like this
SELECT
DATEPART(MM, CONVERT(DATE, 'May' + '01, 2000', 110))
MonthName,
SUM(ExpenseClaimCount) AS Expr1,
'EXPENSE-CLAIM' AS ROW_TYPE
FROM
(SELECT b.OrganisationID,
a.ExpenseClaimCount,
c.MonthName
FROM Fact.MonthlyFactOrgMap AS a
INNER JOIN Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey
INNER JOIN Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014)
AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate)
AND (c.MonthName IN ('March',
'April',
'May',
'June'))
AND (a.ExpenseClaimCount > 0)) AS q
GROUP BY DATEPART(MM, CONVERT(DATE, 'May' + '01, 2000', 110)), MonthName
ORDER BY DATEPART(MM, CONVERT(DATE, 'May' + '01, 2000', 110))
Assuming monthname
matches the month in fulldate
:
SELECT MonthName,
SUM(ExpenseClaimCount) AS Expr1,
'EXPENSE-CLAIM' AS ROW_TYPE
FROM
(
SELECT b.OrganisationID,
a.ExpenseClaimCount,
c.MonthName,
c.FullDate
FROM Fact.MonthlyFactOrgMap AS a
INNER JOIN Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey
INNER JOIN Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014)
AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate)
AND (c.MonthName IN ('March', 'April', 'May', 'June'))
AND (a.ExpenseClaimCount > 0)
) AS q
GROUP BY MonthName
order by (DATEPART(month,FullDate) + 8) % 12
Otherwise you'll need to join a table giving the date order to your table to get a numeric version of the month name; example here using a common table expression to generate a virtual table for this purpose:
;with cteMonths (name, monthDate) as
(
select datename(month,'1900-01-01'), cast('1900-01-01' as date)
union all
select DATENAME(month,dateadd(month,1,monthdate))
,dateadd(month,1,monthdate)
from ctemonths
where monthDate < '1900-12-01'
)
SELECT MonthName,
SUM(ExpenseClaimCount) AS Expr1,
'EXPENSE-CLAIM' AS ROW_TYPE
FROM
(
SELECT b.OrganisationID,
a.ExpenseClaimCount,
c.MonthName
FROM Fact.MonthlyFactOrgMap AS a
INNER JOIN Dim.DimOrganisation AS b ON a.DimOrganisationKey = b.DimOrganisationKey
INNER JOIN Dim.DimDate AS c ON a.DateKey = c.DateKey
WHERE (c.CalendarYear = 2014)
AND (c.FullDate BETWEEN b.RowStartDate AND b.RowEndDate)
AND (c.MonthName IN ('March', 'April', 'May', 'June'))
AND (a.ExpenseClaimCount > 0)
) AS q
inner join
(
select name
, (DATEPART(month,monthdate) + 8) % 12 displayOrder
from cteMonths
) x
on x.name = q.monthname
GROUP BY MonthName
order by x.displayOrder
Explanation
(DATEPART(month,fulldate) + 8) % 12
is the important bit of this code.
datepart
extracts the numeric value of the month (eg 2014-07-03
-> 7)
% 12
means is the mathematic modulus function; ie what's the remainder after I divide this number by 12; so 7 % 12
is 7, 12 % 12
is 0, and 14 % 12
is 2.
+8
provides an offset to make April the first month; since 4 (april) + 8 = 12, and 12 % 12 = 0, making this the first in the sequence.
I did +8
instead of -4
as a workaround for a SQL nuance; in SQL -1 % 12
is -1; in most other systems it would be 11. By adding 8 we avoid the need to deal with negative numbers, so avoid this issue.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.