How can i filter a datetime column using a where clause - sql-server-express

I need to filter a datetime column which is named Departure.
I need the filter to return all prices <=100 and where the departure date is between 2105-03-14 and 2015-03-17 and the departure time on these dates is from 1pm onwards.
I tried the code below. The joins work properly but the where clause is the problem. Can anyone help.
Select Destination,Departure,Price
From PriceTable as p
Join Routes as r
On p.RouteID = r.ID
Join Destinations as d
On d.Airport_ICAO_Code = r.Airport_ICAO_Code
Where (Price <= 100) And (Departure between '2015-03-14' and '2015-03-17' >= '13:00:00')
Order by Price Asc

That's not the right syntax to filter the records after some xx:xx:xx time. Try this where clause
.....
.....
WHERE Price <= 100
AND Departure BETWEEN '2015-03-14' AND '2015-03-17'
AND CONVERT(TIME, Departure) >= '13:00:00'
.....

Related

Redshift - Adding dates (month interval) between two dates

Using Amazon Redshift.
Also have a dates table with all calendar dates that can be utilized.
Question: How can I take a start timestamp (created_at) and end timestamp (ended_at) and add a column that adds 1 month to the start timestamp until the end timestamp.
I have a table with:
user_id,
plan_id,
created_at,
ended_at, (can be null)
So if I had a created_at timestamp of 2019-07-11, I would have a column with additional rows for 2019-08-11, 2019-09-11, 2019-10-11, etc. The goal is to associate the monthly amounts paid by a user to the dates when starting with only a start and end date.
EDIT:
I used the below query which works when an ended_at timestamp is present, however, when it is null, I need to have the next month populated until an ended_at timestamp is present.
select
ps.network_id,
ps.user_id,
ps.plan_id,
ps.created_at,
extract('day' from ps.created_at) as extract_day,
d.calendar_date,
ps.archived_at as ended_at,
ps.application_fee_percent,
pp.amount,
pp.interval,
pp.name
from payments_subscriptions ps
left outer join dates d on extract('day' from date_trunc('day',d.calendar_date)) = extract('day' from ps.created_at) AND date_trunc('day',d.calendar_date) >= date_trunc('day',ps.created_at) AND date_trunc('day',d.calendar_date) < date_trunc('day',ps.archived_at)
left outer join payments_plans pp on ps.plan_id = pp.id
where ps.network_id = '1318990'
and ps.user_id = '2343404'
order by 3,6 desc
output from above query - subscription with null ended_at needs to continue until ended_at is present
Use dateadd function for increasing time/date in timestamp
https://docs.aws.amazon.com/redshift/latest/dg/r_DATEADD_function.html
For increasing one month use this:
DATEADD(month, 1, CURRENT_TIMESTAMP)
For anyone looking for a potential solution, I ended up joining my dates table in this fashion:
LEFT OUTER JOIN dates d ON extract('day' FROM date_trunc('day',d.calendar_date)) = extract('day' FROM payments_subscriptions.created_at)
AND date_trunc('day',d.calendar_date) >= date_trunc('day',payments_subscriptions.created_at)
AND date_trunc('day',d.calendar_date) < date_trunc('day',getdate())
and this where clause:
WHERE (calendar_date < date_trunc('day',payments_subscriptions.archived_at) OR payments_subscriptions.archived_at is null)

Sampling issue with query in BigQuery (Standard SQL)

I have been running a query of the format below
SELECT b.date as Date,COUNT(DISTINCT user_id) AS NewUsers FROM (
SELECT user_id,MIN(date) as min_date
FROM tableA
WHERE date >= '2018-10-10'
AND filter1 = "XYZ"
GROUP BY ) a
CROSS JOIN (
SELECT date FROM tableB
WHERE date >= '2018-10-19' AND date <= CURRENT_DATE()
GROUP BY 1) b
WHERE a.date >= DATE_SUB(b.date, INTERVAL 6 DAY) AND a.date <= b.date
GROUP BY 1
Let's say the above is result1
SELECT b.date as Date,COUNT(DISTINCT user_id) AS NewUsers FROM (
SELECT user_id,MIN(date) as min_date
FROM tableA
WHERE date >= '2018-07-10'
AND filter1 = "XYZ"
GROUP BY ) a
CROSS JOIN (
SELECT date FROM tableB
WHERE date >= '2018-07-19' AND date <= CURRENT_DATE()
GROUP BY 1) b
WHERE a.date >= DATE_SUB(b.date, INTERVAL 6 DAY) AND a.date <= b.date
GROUP BY 1
The above is result2
Here 2018-07-19 is the launch date.
Since I have the data till 2018-10-19, I want to run the query from the later date to optimize the cost and the data consumption by the query....but some how, I am getting incorrect data.
But, if I run the same query from the launch date, I am getting the correct results.
I mean the NewUsers from result1 for the corresponding dates (like date >= 2018-10-19) are more than the NewUsers from result2.
No sure, where I am missing something.
Any help would be greatly appreciated.
Thanks
I think - it is because of use of 'MIN(date)' - You see shift in counts because you restricted dates so those users who were first seen in earlier dates - now those same "old" users are counted for recent days - thus the confusion

SQL creating a pivot function

I have a SQL code that looks like this:
select cast(avg(age) as decimal(16,2)) as 'avg' From
(select distinct acct.Account, cast(Avg(year(getdate())- year(client_birth_date)) as decimal(16,2)) as 'Age'
from WF_PM_ACCT_DB DET
inner join WF_PM_ACCT_DET_DB ACCT
ON det.Account = acct.Account
where (acct_closing_date is null or acct_closing_date > '2017-01-01')
and Acct_Open_Date < '2017-01-01'
group by acct.Account
) x
Then basically what this give me is a simple one cell answer of the average age of accounts in the year Acct_Open_Date < '2017-01-01' . I am an ameture so i change the date everytime and run the query again and again to get the remaining year. Is there an easy way to say lets have all the years as column headings and just one row with the average account age in that year.
Please note that the account closing date being null means accounts never got close and i have to change it to less than the analysis year in order to get a true picture of the average account age that existed at that time
Any help is appreciated. Thanks.
You can run this for multiple dates by including them in a single derived table:
with dates as (
select cast('2017-01-01' as date) as yyyy union all
select cast('2016-01-01' as date)
)
select yyyy, cast(avg(age) as decimal(16,2)) as avg_age
From (select dates.yyyy, acct.Account,
cast(Avg(year(getdate())- year(client_birth_date)) as decimal(16,2)) as Age
from dates cross join
WF_PM_ACCT_DB DET inner join WF_PM_ACCT_DET_DB
ACCT
on det.Account = acct.Account
where (acct_closing_date is null or acct_closing_date > dates.yyyy) and
Acct_Open_Date < dates.yyyy
group by acct.Account, dates.yyyy
) x
group by yyyy
order by yyyy;

How to select all dates in SQL query

SELECT oi.created_at, count(oi.id_order_item)
FROM order_item oi
The result is the follwoing:
2016-05-05 1562
2016-05-06 3865
2016-05-09 1
...etc
The problem is that I need information for all days even if there were no id_order_item for this date.
Expected result:
Date Quantity
2016-05-05 1562
2016-05-06 3865
2016-05-07 0
2016-05-08 0
2016-05-09 1
You can't count something that is not in the database. So you need to generate the missing dates in order to be able to "count" them.
SELECT d.dt, count(oi.id_order_item)
FROM (
select dt::date
from generate_series(
(select min(created_at) from order_item),
(select max(created_at) from order_item), interval '1' day) as x (dt)
) d
left join order_item oi on oi.created_at = d.dt
group by d.dt
order by d.dt;
The query gets the minimum and maximum date form the existing order items.
If you want the count for a specific date range you can remove the sub-selects:
SELECT d.dt, count(oi.id_order_item)
FROM (
select dt::date
from generate_series(date '2016-05-01', date '2016-05-31', interval '1' day) as x (dt)
) d
left join order_item oi on oi.created_at = d.dt
group by d.dt
order by d.dt;
SQLFiddle: http://sqlfiddle.com/#!15/49024/5
Friend, Postgresql Count function ignores Null values. It literally does not consider null values in the column you are searching. For this reason you need to include oi.created_at in a Group By clause
PostgreSql searches row by row sequentially. Because an integral part of your query is Count, and count basically stops the query for that row, your dates with null id_order_item are being ignored. If you group by oi.created_at this column will trump the count and return 0 values for you.
SELECT oi.created_at, count(oi.id_order_item)
FROM order_item oi
Group by io.created_at
From TechontheNet (my most trusted source of information):
Because you have listed one column in your SELECT statement that is not encapsulated in the count function, you must use a GROUP BY clause. The department field must, therefore, be listed in the GROUP BY section.
Some info on Count in PostgreSql
http://www.postgresqltutorial.com/postgresql-count-function/
http://www.techonthenet.com/postgresql/functions/count.php
Solution #1 You need Date Table where you stored all date data. Then do a left join depending on period.
Solution #2
WITH DateTable AS
(
SELECT DATEADD(dd, 1, CONVERT(DATETIME, GETDATE())) AS CreateDateTime, 1 AS Cnter
UNION ALL
SELECT DATEADD(dd, -1, CreateDateTime), DateTable.Cnter + 1
FROM DateTable
WHERE DateTable.Cnter + 1 <= 5
)
Generate Temporary table based on your input and then do a left Join.

MSSQL select count where condition is met across a date range

I have a table containing date, employeeID(int) , and ShiftWorked (can be night/day/weekend or evening) . There is a row for each employee and date combination
I would like to construct a query that gives me a count of how many people have worked a night shift in the week before and after each date in the roster period.
--------------------------------------------------------------------------
Date (yyyy-MM-dd) | CountOfNightshifts(for 1 week either side of date)
--------------------------------------------------------------------------
2012-1-1 | 8
2012-1-2 | 12
2012-1-3 | 11
2012-1-4 | 6
etc | etc
I hope this is clear. I have spent days trying to get this to work but I am not getting anywhere.
For example:
SELECT COUNT(id), [date]
FROM ROSTER
WHERE Shift = night AND [date] BETWEEN DATEADD(D,-7,[date]) AND DATEADD(d,7,[date])
GROUP by [date]
group by [date]
This will give me a list of dates and a count of nights on that particular day - not all night shifts in the 7 days before and after the date.
The following query will return two columns: the reference (roster) date and the number of (distinct) people that have worked on the night sift seven days before to seven days after the reference date.
SELECT tmain.date,
(
SELECT COUNT(DISTINCT taux.employeeId)
FROM roster taux
WHERE taux.shiftWorked = 'night'
AND taux.date >= DATEADD(DAY, -7, tmain.date)
AND taux.date <= DATEADD(DAY, 7, tmain.date)
) AS [number_of_distinct_people_with_night_shift]
FROM roster tmain
ORDER BY tmain.date;
Note 1: Usually I prefer joins over sub-queries, but I guess this solution is easier to read.
Note 2: I am assuming the time component of date values are irrelevant and all dates have the same time (i.e. '00:00:00.00'); if it is not the case, there are more adjustments to be done on the date comparison.
how about this?
SELECT
[date]
,count(*)
FROM
Shifts as s
WHERE
s.Date > DATEADD(day,-7,GETDATE())
AND ShiftWorked = 'Night'
GROUP BY
date
http://sqlfiddle.com/#!3/e88cc/1
a bit more data:
http://sqlfiddle.com/#!3/b7793/2
If you are only interested in a specific date then you could use:
DECLARE #target datetime
SET #target = GETDATE()
SELECT
count(*) as NightShifts
FROM
Shifts as s
WHERE
ShiftWorked = 'Night'
AND s.Date > DATEADD(day,-7,#target)
AND s.Date < DATEADD(day,7,#target)
http://sqlfiddle.com/#!3/b7793/20
but if you have another table that actually has the periods in it (e.g. billing or payroll dates):
DECLARE #target datetime
SET #target = GETDATE()
SELECT
p.periodDate
,count(*)
FROM
Shifts as s
INNER JOIN periods as p
ON s.date > dateadd(day,-7,p.periodDate)
AND s.date < dateadd(day,7,p.periodDate)
WHERE
ShiftWorked = 'Night'
GROUP BY p.periodDate
http://sqlfiddle.com/#!3/fc54d/2
OR to get ) when no night shift was worked:
SELECT
p.periodDate
,ISNULL(t.num,0) as nightShifts
FROM
periods as p
LEFT OUTER JOIN (
SELECT
p.periodDate
,count(*) as num
FROM
Shifts as s
INNER JOIN periods as P
ON s.date > dateadd(day,-7,p.periodDate)
AND s.date < dateadd(day,7,p.periodDate)
WHERE
ShiftWorked = 'Night'
GROUP BY p.periodDate
) as t
ON p.periodDate = t.periodDate
http://sqlfiddle.com/#!3/fc54d/11
You can pull it off by joining the ROSTER table to itself, thereby creating several result rows per employee and day. Otherwise your GROUP BY clause will group the resulting rows from the period you are after into the dates of the original table.
SELECT
r.[date],
COUNT(period.id)
FROM ROSTER r
JOIN ROSTER period
ON period.employeeID=r.employeeID
AND period.shift = night
AND r.[date] BETWEEN DATEADD(d,-7,period.[date]) and DATEADD(d,7,period.[date])
WHERE
r.shift = night
GROUP BY r.[date]