Using resulting field in ORDER BY - tsql

I will post a simple example:
SELECT " CAST(t.PurchaseDate AS DATE) AS PurchaseDate
FROM SomeTable t
ORDER BT PurchaseDate
How can I make sure that ORDER BY will use PurchaseDate (only DATE part), and not PurchaseDate table field?
I know I can name CAST result as PurchaseDate2 (or whatever), but I do not see that as a very intuitive solution.
SELECT " CAST(t.PurchaseDate AS DATE) AS PurchaseDate2
FROM SomeTable t
ORDER BT PurchaseDate2
Also I can use CAST again:
ORDER BY CAST(t.PurchaseDate AS DATE)
but I am wondering if I can avoid double CAST?
Any ideas how can we (and can we) reference a resulting field in ORDER BY, and not the table field, when they have the same name?

Syntax of the '' aside....It's not a solution, as the order by clause uses table column names, not statement alias names. If you're looking for something this specific:
SELECT " PurchaseDate
FROM (
SELECT " CAST(t.PurchaseDate AS DATE) AS PurchaseDate
FROM SomeTable t
) AnotherTable
ORDER BT PurchaseDate

You can use CONVERT() function as below which will get only DATE part
SELECT CONVERT(date, t.PurchaseDate) AS PurchaseDate
FROM SomeTable t
ORDER BT PurchaseDate
First of all, you should change the alias name to different then actual column name. Something like NewPurchaseDate. Not sure why you want to keep it same like actual column name.
second, you can do something like below, instead of using the column alias use the actual conversion processing in order by
SELECT CONVERT(date, t.PurchaseDate) AS PurchaseDate
FROM SomeTable t
ORDER BY CONVERT(date, t.PurchaseDate)

Does not have the ugly factor of PurchaseDate2
SELECT CAST(t.PurchaseDate AS DATE) AS [Purchase Date]
FROM SomeTable t
ORDER BY [Purchase Date]

Related

How to store a temporary value in a Postgresql query and then use it multiple times?

I have this simple query:
SELECT COUNT(*)
FROM CompressorAlerts
WHERE CAST('2020-09-20' as timestamp) IS NULL OR faultTimestamp >= CAST('2020-09-20' as timestamp)
(I hardcoded 2020-09-20 ... it is really a value I am getting from somewhere else, irrelevant to this question, but I hardcoded it for simplicity).
As you can see, I am repeating twice CAST('2020-09-20' as timestamp). I want to avoid that, so I tried doing this:
WITH myDate as (SELECT CAST('2020-09-20' as timestamp))
SELECT COUNT(*)
FROM CompressorAlerts
WHERE myDate IS NULL OR faultTimestamp >= myDate
However, I get this error: column "mydate" does not exist.
How can I reference the myDate value I defined in the WITH clause? Am I doing something wrong?
mydate is the name of the CTE, not the name of the column expression inside it. Additionally you need to include the CTE in the FROM part of the query.
WITH params (mydate) as (
values (timestamp '2020-09-20')
)
SELECT COUNT(*)
FROM CompressorAlerts, params
WHERE mydate IS NULL
OR faultTimestamp >= mydate

DB2: substring a number

In my dataset I have a variable (numeric) which is year+month, called year_month with values 201702, 201703 etc.
Normally my code looks like this:
select
year_month
,variable2
,variable3
from dataset
I wish to extract the month and the year from the year_month variable, but I'm not sure how to do this when year_month is numeric.
edit: not a duplicate, different problem, I do not care about dates.
To extract the date parts from an integer
SELECT year_month/100,MOD(year_month,100)
To fully convert the integer to a date :
SELECT TO_DATE(CHAR(year_month),'YYYYMM')
Possible with this methods too:
select left(cast(year_mont as varchar(6)), 4) as YYYY,
right(cast(year_mont as varchar(6)), 2) as MM from yourtable
You can have a timestamp like this:
select TIMESTAMP_FORMAT(cast(year_mont as varchar(6)), 'YYYYMM') as YouTimeStamp
from yourtable
Or a date too:
select Date(TIMESTAMP_FORMAT(cast(year_mont as varchar(6)), 'YYYYMM')) as YouTimeStamp
from yourtable

T-SQL apply where clause to function fields not working

I'm having a hard time filtering this view by CreateDate. The CreateDate in the table is in the following format: 2013-10-14 15:53:33.900
I managed to DATEPART the year month and day into separate columns, but now it's not letting me use my WHERE clause on those newly created columns. Specifically, the error is "Invalid Column Name CreateYear" for both lines. What am I doing wrong here guys? Is there a better/easier way to do this than parse out the day, month, and year? It seems overkill. I've spent quite a bit of hours on this to no avail.
SELECT convert(varchar, DATEPART(month,v.CreateDate)) CreateMonth,
convert(varchar, DATEPART(DAY,v.CreateDate)) CreateDay,
convert(varchar, DATEPART(YEAR,v.CreateDate)) CreateYear,
v.CreateDate,
v.customerName
From
vw_Name_SQL_DailyPartsUsage v
full outer join
ABC.serviceteamstechnicians t on v.TechnicianNumber = t.AgentNumber
full outer join
ABC.ServiceTeams s on t.STID = s.STID
where
CreateYear >= '02/01/2018'
and
CreateYear <= '02/20/2018'
You cannot reference an alias from the select in the where
Even if you could why would you expect year to be '02/01/2018'
Why are you converting to varchar
where year(v.CreateDate) = 2018
or
select crdate, cast(crdate as date), year(crdate), month(crdate), day(crdate)
from sysObjects
where cast(crdate as date) <= '2014-2-20'
and cast(crdate as date) >= '2000-2-10'
order by crdate
You could use:
SELECT convert(varchar, DATEPART(month,v.CreateDate)) CreateMonth,
convert(varchar, DATEPART(DAY,v.CreateDate)) CreateDay,
convert(varchar, DATEPART(YEAR,v.CreateDate)) CreateYear,
v.CreateDate,
v.customerName
From vw_Name_SQL_DailyPartsUsage v
full outer join
ABC.serviceteamstechnicians t on v.TechnicianNumber = t.AgentNumber
full outer join
ABC.ServiceTeams s on t.STID = s.STID
where CreateDate BETWEEN '20180102' and '20180220';
More info about the logical query processing is that you cannot refer to a column alias at SELECT in the WHERE clause without using a subquery/CROSS APPLY.

PostgreSQL crosstab() alternative with CASE and aggregates

I want to create a pivot table view showing month on month sum of bookings for every travel_mode.
Table bookings:
timestamp
, bookings
, provider_id
Table providers:
provider_id
, travel_mode
Pivot table function and crosstab functions are not to be used to do this. So I am trying to use JOIN and CASE. Following is the query:
SELECT b.month,
(CASE WHEN p.travel_mode=train then b.amount end)train,
(CASE WHEN p.travel_mode=bus then b.amount end)bus,
(CASE WHEN p.travel_mode=air then b.amount end)air
FROM
(SELECT to_char(date_,month) as month, travel_mode, sum(bookings) as amount
from bookings as b
join providers as p
on b.provider_id=p.provider_id
group by b.month, p.travel_mode)
group by b.month;
However I am getting an error which says:
subquery in FROM must have an alias LINE 6:
And when I add an alias it throws an error saying:
column p.travel_mode must appear in the GROUP BY clause or be used in an aggregate function
LINE 2:
The final result should be something like this
Month Air Bus Train
01 Amount(air) Amount(Bus) Amount(train)
I have a feeling it is a minor error somewhere but I am unable to figure it out at all.
P.S. I had to remove all quotations in the question as it was not allowing me to post this. But those are being taken care of in the actual query.
Multiple problems. The missing table alias is just one of them. This query should work:
SELECT month
, sum(CASE WHEN travel_mode = 'train' THEN amount END) AS train
, sum(CASE WHEN travel_mode = 'bus' THEN amount END) AS bus
, sum(CASE WHEN travel_mode = 'air' THEN amount END) AS air
FROM (
SELECT to_char(timestamp, 'MM') AS month, travel_mode, sum(bookings) AS amount
FROM bookings b
JOIN providers p USING (provider_id)
GROUP BY month, p.travel_mode
) sub
GROUP BY month;
Missing single quotes for string literals. (You seem to have removed those being under the wrong impression you couldn't post quotations.)
Missing table alias for the subquery - just like the 1st error message says.
In the outer query, table names (or aliases) of underlying tables in the subquery are not visible. Only the table alias of the subquery is. Since there is only one subquery, you don't need table-qualification at all there.
month is an output column name (not in the underlying table), so the table qualification b.month was wrong, too.
You seem to want 2-digit numbers for months. Use the template pattern 'MM' instead of 'month' with to_char().
The aggregation in the outer query does not work like you had it - just like your 2nd error message says. You have to wrap the outer CASE expression in a aggregate function. You might as well use min() or max() in this case, because there are never more than one rows after the subquery.
Still unclear where date_ is coming from? You mean timestamp? (which is not a good identifier).
But you don't need the subquery to begin with and can simplify to:
SELECT to_char(timestamp, 'MM') AS month
, sum(CASE WHEN p.travel_mode = 'train' THEN b.bookings END) AS train
, sum(CASE WHEN p.travel_mode = 'bus' THEN b.bookings END) AS bus
, sum(CASE WHEN p.travel_mode = 'air' THEN b.bookings END) AS air
FROM bookings b
JOIN providers p USING (provider_id)
GROUP BY 1;
For best performance you should still use crosstab(), though:
PostgreSQL Crosstab Query
You have to name the subquery as the error message says:
SELECT b.month,
(CASE WHEN p.travel_mode=train then b.amount end)train,
(CASE WHEN p.travel_mode=bus then b.amount end)bus,
(CASE WHEN p.travel_mode=air then b.amount end)air
FROM
(SELECT to_char(date_,month) as month, travel_mode, sum(bookings) as amount
from bookings as b
join providers as p
on b.provider_id=p.provider_id
group by b.month, p.travel_mode)
**as foo** group by b.month;
Remove the stars to make it work.

How to sort this data inside the field based on the recent Date

I have a data in the field as " Date: 03-21-13 12/13/14/15 Date:04-21-13 39/12/34/14 Date:04-19-13 19/45/65/12 ".How to sort this data inside the field based on the recent Date.
It should Look like
Date:04-21-13 39/12/34/14
Date:04-19-13 19/45/65/12
Date: 03-21-13 12/13/14/15
Because you are storing it as text, you cannot correctly sort directly on the column (as you appear to have discovered). You will need to split the column, and then sort on that. Something like:
Declare #tvTable Table (
TextColumn varchar(max)
)
Insert #tvTable
Select '04-19-13 19/45/65/12'
Union All
Select '04-21-13 39/12/34/14'
Union All
Select '03-21-13 12/13/14/15'
Union All
Select '03-25-13 17/18/19/20'
Union All
Select '05-01-13 99/88/77/66'
Union All
Select '02-01-13 11/22/33/44'
Select t.TextColumn
From #tvTable t
Cross Apply dbo.fncDelimitedSplit8k(TextColumn, ' ') split
Where split.ItemNumber = 1
Order By Cast(split.Item As DateTime) Desc
The split function taken from Jeff Moden Tally OH!