How to order by column not in select clause? - sql

Is there a method to work around not being able to sort by a column not in the select clause? I am using datename to grabe month and year, but i need it to be sorted by actual date not alphabetically.
select datename(month, dbo.ITR.ITR_TransDate) as MonthDt,
DATENAME(year, dbo.itr.ITR_TransDate) as YearDt, COUNT(distinct dbo.ITR.ITR_Reason) AS WKCount, COUNT(dbo.itr.itr_reason) AS LineCt
from dbo.ITR
where (ITR_EmployeeID IN (N'robra', N'lewer', N'petam', N'whike', N'mclch', N'ricju')) AND (dbo.ITR.ITR_TransDate >= '1/1/13' AND dbo.itr.ITR_TransDate <= '1/31/14') AND
(dbo.itr.ITR_Reason LIKE 'WO%' OR dbo.itr.ITR_Reason LIKE 'RW%')
group by DATENAME(year, dbo.itr.ITR_TransDate), datename(month, dbo.ITR.ITR_TransDate), MONTH(dbo.itr.itr_transdate)
order by dbo.ITR.ITR_TransDate
the order by i have is failing b/c it isn't in the group by or an aggregate. i can't add it to either b/c there are many many dates that it would return.

You can just use an aggregation function in the order by:
order by min(dbo.ITR.ITR_TransDate)
This should work for your case.

try this
select datename(month, dbo.ITR.ITR_TransDate) as MonthDt,
DATENAME(year, dbo.itr.ITR_TransDate) as YearDt, COUNT(distinct dbo.ITR.ITR_Reason) AS WKCount, COUNT(dbo.itr.itr_reason) AS LineCt
from dbo.ITR
where (ITR_EmployeeID IN (N'robra', N'lewer', N'petam', N'whike', N'mclch', N'ricju')) AND (dbo.ITR.ITR_TransDate >= '1/1/13' AND dbo.itr.ITR_TransDate <= '1/31/14') AND
(dbo.itr.ITR_Reason LIKE 'WO%' OR dbo.itr.ITR_Reason LIKE 'RW%')
group by DATENAME(year, dbo.itr.ITR_TransDate), datename(month, dbo.ITR.ITR_TransDate), MONTH(dbo.itr.itr_transdate)
order by DATENAME(year, dbo.itr.ITR_TransDate), MONTH(dbo.itr.itr_transdate)

Related

SQL - Why doesn't using alias in Group By doesn't work in SQL server

Why can't I use Alias even after nesting the code, it seems to not work, I used a different approach which works but doesn't look good.
This doesn't work
SELECT Year,
Number_of_rides
FROM (SELECT DATEPART(YEAR, [starttime]) AS Year,
COUNT (*) AS Number_of_rides
FROM [dbo].[Citi-Bike-Trip-Data]) AS x
GROUP BY x.Year,
x.Number_of_rides
ORDER BY Year ASC
This works
SELECT
DATEPART(YEAR,
[starttime]) AS Year,
COUNT (*) AS Number_of_rides
FROM
[dbo].[Citi-Bike-Trip-Data]
GROUP BY DATEPART(YEAR, [starttime])
As noted by others, the problem is not with the alias. You are missing group by in the subquery, which is required since you are using count there:
SELECT [Year],
Number_of_rides
FROM (SELECT DATEPART(YEAR, [starttime]) AS [Year],
COUNT (*) AS Number_of_rides
FROM [dbo].[Citi-Bike-Trip-Data]
GROUP BY DATEPART(YEAR, [starttime])) AS x
GROUP BY x.Year,
x.Number_of_rides
ORDER BY [Year] ASC
Since the data is already grouped in the subquery, you don't need to group again:
SELECT [Year],
Number_of_rides
FROM (SELECT DATEPART(YEAR, [starttime]) AS [Year],
COUNT (*) AS Number_of_rides
FROM [dbo].[Citi-Bike-Trip-Data]
GROUP BY DATEPART(YEAR, [starttime])) AS x
ORDER BY [Year] ASC
And since the data is already grouped and already exactly what you want, you really don't need to select it again, so:
SELECT DATEPART(YEAR, starttime) AS [Year],
COUNT (*) AS Number_of_rides
FROM dbo.Citi-Bike-Trip-Data
GROUP BY DATEPART(YEAR, starttime)
ORDER BY [Year]
Which is almost like your original second version, but only adding in the order by.
The problem is you need to group by in your subquery, so use this:
SELECT datepart(year, x.starttime) as Year, x.Number_of_rides
from
(
select [starttime], COUNT (*) AS Number_of_rides
FROM [dbo].[Citi-Bike-Trip-Data]
GROUP BY [starttime]
) as x
Order by x.[starttime] ASC
Only select the columns in your subquery, and then use datepart(year, x.starttime) in your outer query would be a good solution.
Or a cte would do same thing.
If you need to group by year, then the only solution I can think of is using group by datepart(year, starttime) as your second query, as you can only use computed column names in order by clause, but not in where or group by.

SQL How can I get a count of messages going out by month

I have a table that sends out messages, I would like to get a total count of the messages that have been going out month by month over the last year . I am new to SQL so I am having trouble with it . I am using MSSQL 2012 this is my sql
SELECT sentDateTime, MessageID, status AS total, CONVERT(NVARCHAR(10), sentDateTime, 120) AS Month
FROM MessageTable
WHERE CAST(sentDateTime AS DATE) > '2017-04-01'
GROUP BY CONVERT(NVARCHAR(10), sentDateTime, 120), sentDateTime, MessageID, status
ORDER BY Month;
I think the month() and year() functions are more convenient than datepart() for this purpose.
I would go for:
select year(sentDateTime) as yr, month(sentDateTime) as mon, count(*)
from MessageTable
where sentDateTime > '2017-04-01'
group by year(sentDateTime), month(sentDateTime)
order by min(sentDateTime);
Additional notes:
Only include the columns in the select that you care about. This would be the ones that define the month and the count.
Only include the columns in the group by that you care about. Every combination of the expressions in the group by found in the data define a column.
There is no need to convert sentDateTime to a date explicitly for the comparison.
The order by orders the results by time. Using the min() is a nice convenience.
Including the year() makes sure you don't make a mistake -- say by including data from 2018-04 with 2017-04.
-- this selects the part of the date you are looking for, replace this with the date format you are using, this should give you what you are looking for
SELECT DATEPART(mm, GETDATE())
SELECT COUNT(DATEPART(mm, sentDateTime)), MessageID, status
From MessageTable where Cast(sentDateTime as date) > '2017-04-01'
group by DATEPART(mm, sentDateTime), MessageID, status
order by DATEPART(mm, sentDateTime)
You can group by the month number of the sentDateTime with the function DATEPART(MONTH, sentDateTime). The next select will also yield results if no message was sent for a particular month (total = 0).
;WITH PossibleMonths AS
(
SELECT
M.PossibleMonth
FROM
(VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) M(PossibleMonth)
),
MonthTotals AS
(
select
COUNT(1) AS Total,
DATEPART(MONTH, sentDateTime) [Month]
From
MessageTable
where
Cast(sentDateTime as date) > '2017-04-01'
group by
DATEPART(MONTH, sentDateTime)
)
SELECT
P.PossibleMonth,
Total = ISNULL(T.Total, 0)
FROM
PossibleMonths AS P
LEFT JOIN MonthTotals AS T ON P.PossibleMonth = T.Month

How to count records by branch and year sql server

I want to count projects by branch and by the year.
I tried this code but does not work. Any help is appreciated.
SELECT COUNT(ProjectIndentID) AS NoOfProjects, BranchID, DATEPART(year, PIDate) AS Expr1
FROM dbo.ProjectIndent
GROUP BY BranchID, PIDate
HAVING (DATEPART(year, PIDate) = '2016')
You need to group by the year, not the date:
SELECT COUNT(ProjectIndentID) AS NoOfProjects, BranchID,
DATEPART(year, PIDate) AS yr
FROM dbo.ProjectIndent
WHERE DATEPART(year, PIDate) = 2016
GROUP BY BranchId, DATEPART(year, PIDate) ;
In addition:
The having logic should really be in a where clause. It is better to filter the data before aggregation, rather than afterwords.
DATEPART() returns an integers, so use 2016 rather than '2016'.
You probably want an ORDER BY.
The WHERE clause should really be `WHERE PIDate >= '2016-01-01' AND PIDate < '2017-01-01'. This allows an index to be used for the filtering (if appropriate).

How to combine multiple rows from the same column that have the same data?

The code I have is:
SELECT datepart(year, request_created_date) AS request_year,
datepart(month, request_created_date) AS request_month,
datepart(week, request_created_date) AS request_week,
count(request_id) AS request_count
FROM nyc311_requests
GROUP BY request_created_date
ORDER BY request_week
In the output I'm getting, I have two rows where request_week is 36 and 7 rows where it's 37. What I want is to combine columns like that into one row.
If you are going to use a GROUP BY clause, you are going to have to include all the fields in other than the calculated field in the GROUP BY:
SELECT datepart(year, request_created_date) AS request_year,
datepart(month, request_created_date) AS request_month,
datepart(week, request_created_date) AS request_week,
count(request_id) AS request_count
FROM nyc311_requests
GROUP BY datepart(year, request_created_date),
datepart(month, request_created_date),
datepart(week, request_created_date)
ORDER BY request_week
Or, if you want a cleaner looking query:
SELECT M.*, count(*) AS request_count FROM
(
SELECT datepart(year, request_created_date) AS request_year,
datepart(month, request_created_date) AS request_month,
datepart(week, request_created_date) AS request_week
FROM nyc311_requests
)AS M
GROUP BY M.request_year, M.request_month, M.request_week
ORDER BY M.request_week

Grouping by Week in SQL, but displaying full datetime?

the following statement:
group by datepart(wk, createdon)
Groups the selected rows according to the week in which they fall. My select statement shows the following:
SELECT
datepart(wk, createdon) week,
How do I display the actual datetime of the week("12-10-2012"), instead of the number ("12")?
If I understand you correctly, you're wanting to group by week but also return the full datetime. You must include the selected fields in aggregate columns.
Thusly should work:
SELECT DATEPART(wk, createdon) week, createdon
FROM TableName
GROUP BY DATEPART(wk, createdon), createdon
Works on MSSQL2008R2
Edit:
As the OP seems to want the starting date of the week, SO has the answer.
One option is using a cte with ROW_NUMBER instead:
WITH CTE AS
(
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY datepart(wk, createdon) ORDER BY createdon)
, DATEADD(ww, DATEDIFF(ww,0,createdon), 0) As Week
, *
FROM dbo.Table
)
SELECT * FROM CTE
WHERE RN = 1
You can't group by a week, and then show constituent parts of it, i.e. days. You will need group by the date instead.