SQL Server 2012 query date - sql-server

How can I return values in a where clause for something like this:
Get me all the records that exist in table1.de1,table2.de2,table3.de3,table4.de3
select *
from table1
inner join table2
on table2.carID = table1.carID
inner join table3
on table3.carID = table1.carID
inner join table4
on table4.driverID = table1.driverID
where a recietrecord exists in table2 and its paydate has passed 20 days ago, comparing it to TODAYS date and show those days in a field called Days Passed From The Day Driver Was Suppose To Pay

At first, please, use table aliases. This solution is for SQL Server:
As was written in comments you can use DATEDIFF function to compare paydate to GETDATE.
select *,
DATEDIFF(day,t2.paydate,GETDATE()) as [Days Passed From The Day Driver Was Suppose To Pay]
from table1 t1
inner join table2 t2
on t2.carID = t1.carID
inner join table3 t3
on t3.carID = t1.carID
inner join table4 t4
on t4.driverID = t1.driverID
WHERE DATEDIFF(day,t2.paydate,GETDATE()) > 20
Or better use minutes:
DATEDIFF(minute,t2.paydate,GETDATE()) > 28800 --60 minutes * 24 hours * 20 days

Related

SQL Server Never Ending when Join Two Tables

I have one source table in DB. I need to do group and sum to get one bridging table, extract supplier info on the other bridging table then join the two using part_number.
If I run the subqueries separately, T1 gives me 54699 records and T2 gives approx 10 times rows of T1.
Next, I do left join, I expect it should return 54699 records, but the server engine never stops and it returns 50 million records at the time I scroll down to the end. I have to stop the query manually. I realized there must something wrong with my query, but I can not figure it out. I would appreciate it if you have any ideas. Thank you!
SELECT
T1.*, T2.SUPPLIER
FROM
(SELECT
T.PART_NUMBER,T.YEAR, T.WEEK,
SUM(T.QTY_FILLED) TOTAL_FILLED,
SUM(T.QTY_ORDERED) TOTAL_ORDERED,
COUNT(T.LINE_NUMBER) ORDER_TIMES
FROM
DBO.TABLE1 T
WHERE
T.YEAR IS NOT NULL
GROUP BY
PART_NUMBER, T.YEAR, T.WEEK) T1
LEFT JOIN
(SELECT
T.PART_NUMBER, T.SUPPLIER
FROM
DBO.TABLE1 T) T2 ON T1.PART_NUMBER = T2.PART_NUMBER
ORDER BY
T1.PART_NUMBER, T1.YEAR, T1.WEEK
I also tried the window function, but still no luck.
WITH T1 AS
(
SELECT
T.PART_NUMBER,T.YEAR, T.WEEK,
SUM(T.QTY_FILLED) TOTAL_FILLED,
SUM(T.QTY_ORDERED) TOTAL_ORDERED,
COUNT(T.LINE_NUMBER) ORDER_TIMES
FROM
DBO.TABLE1 T
WHERE
T.YEAR IS NOT NULL
GROUP BY
PART_NUMBER, T.YEAR, T.WEEK
), T2 AS
(
SELECT T.PART_NUMBER, T.SUPPLIER
FROM DBO.TABLE1 T
)
SELECT
T1.*, T2.SUPPLIER
FROM
T1
LEFT JOIN
T2 ON T1.PART_NUMBER = T2.PART_NUMBER
ORDER BY
T1.PART_NUMBER, T1.YEAR, T1.WEEK
First of all, it not only return 54699 rows. You do a join without distinct, so the result could be the join of 50.000 x 5.000.000 rows and it depends on the value of your table.
If you use SQL 2017 or newer, try something like this:
SELECT
T.PART_NUMBER,T.YEAR, T.WEEK,
SUM(T.QTY_FILLED) TOTAL_FILLED,
SUM(T.QTY_ORDERED) TOTAL_ORDERED,
COUNT(T.LINE_NUMBER) ORDER_TIMES,
STRING_AGG (SUPPLIER, ', ') AS SUPPLIER
FROM
DBO.TABLE1 T
WHERE
T.YEAR IS NOT NULL
GROUP BY
PART_NUMBER, T.YEAR, T.WEEK

Comparing two DATETIME columns in SQL

I have two datetime columns:
StartDate : 2019-07-01 13:30:00.000
AdmitDate : 2019-07-01 00:00:00.000
I want to select all rows that have the same date (excluding the time, seconds, etc).
SELECT *
FROM table1 as t1
INNER JOIN table2 as t2 ON t1.id = t2.id
WHERE t1.startdate >= t2.admitdate or t1.startdate <= t2.admitdate
However, this won't work because one of the columns has hours, minutes and seconds. How to fix this? Again, I just want the date, not time.
The solution is simpler to convert the columns in Date
it depends if both columns are datetime or one is date
SELECT Table1.Id,Table1.Startdate
FROM Table1
INNER JOIN Table2 ON Table1.Id = Table2.Id
where (cast(Table1.Startdate as date))=(cast(Table2.AdmitDateTime as date))
SELECT Table1.Id,Table1.Startdate
FROM Table1
INNER JOIN Table2 ON Table1.Id = Table2.Id
where (cast(Table1.Startdate as date))=Table2.AdmitDate
Example
How about using DATEDIFF()?
SELECT *
FROM table1 as t1
INNER JOIN table2 as t2 ON t1.id = t2.id
WHERE DATEDIFF(DAY, t1.startdate, t2.admitdate) = 0

Data merge in SQL

I tried the below query to display data
select e.Name,ic.Code,t1.pyear,t1.pmonth,t2.Amount
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and t1.pmonth=1
union all
select e.Name,ic.Code,t1.pyear,t1.pmonth,t2.Amount
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and t1.pmonth=2
and the data i am getting is like this-
scode amount month year e_name
abc 3847 1 2016 john
ABC 20938 2 2016 john
XYZ 2838 1 2016 david
XYZ 29384 2 2016 david
now i want to display data like this
s_code amount1 amount2 month1 month2 year e_name
abc 3847 20938 1 2 2016 john
xyz 2838 29384 1 2 2016 david
any solution ?
edit
You could try to use cte. The following is just an example, adjust the column names by yourself because it's a bit of a mess
WITH unionall AS (
select ic.Code, t2.Amount, t1.pmonth, t1.pyear, e.Name
from t1
inner join t2 on t2.id=t1.id
inner join t3 on t3.Code=t2.Code
inner join t4 e on t4.employeeindex=t1.employeeindex
where t1.pyear=2016 and (t1.pmonth=1 OR t2.pmonth=2)
)
SELECT r1.scode, r1.amount as amount1, r2.amount as amount2
FROM unionall r1 inner join unionall r2 on r1.scode = r2.scode
-----------------------
If you know for sure that for each s_code there are 2 months (or at least a costant number) you could easily make a join on itself and select all the values with an alias, like so:
SELECT r1.scode, r1.amount as amount1, r2.amount as amount2 [...more fields...]
FROM result r1 inner join result r2 on r1.scode = r2.scode [...many joins as many months...]
If there can be multiple month that you don't know, i would probably do what on mysql is a group_concat. Basically, you group by scode and then, in the same field, there's a list separated values. Too bad you can't do a group_concat in SQLServer, but there are workaround guides around the web
How to make a query with group_concat in sql server

How to find missing records from one table compared to another table

I have a table called CalTest which has a TransDate Field and an ID Field. I also have a standard Calendar table with dates from 2000 to 2020.
In my CalTest table I have
ID TransDate
1 4/1/2015
2 4/2/2015
3 4/4/2015
4 4/6/2015
I need to run a query where the results will be
Transdate
4/3/2015
4/5/2015
if I run this:
select t1.CalendarDate
FROM Calendar t1
left join Caltest t2 ON t2.TRANSDATE = t1.CalendarDate
where (t2.TRANSDATE IS not NULL)
I get:
TransDate
4/1/2015
4/2/2015
4/4/2015
4/6/2015
If I run this:
select t1.CalendarDate
FROM Calendar t1
left join Caltest t2 ON t2.TRANSDATE = t1.CalendarDate
where (t2.TRANSDATE IS NULL)
I get all the calendarDates from the Calendar table except for:
4/1/2015
4/2/2015
4/4/2015
4/6/2015
And if I run:
select t1.Transdate
FROM Caltest t1
left join Calendar t2 ON t2.CalendarDate = t1.TRANSDATE
where (t2.CalendarDate IS NULL)
I get no results back.
Please let me know what I am doing wrong.
You need to use the calendar table as base since you want to find missing dates.
SELECT c.CalendarDate
FROM Calendar c
LEFT OUTER JOIN Caltest t
ON c.CalendarDate = t.TRANSDATE
WHERE c.CalendarDate >= (SELECT MIN(t2.TRANSDATE) FROM Caltest t2)
AND c.CalendarDate <= (SELECT MAX(t2.TRANSDATE) FROM Caltest t2)
AND t.ID IS NULL
Sounds like you need to constrain the Calendar table to be just the time frame of the Transaction table.
select t1.CalendarDate
FROM Calendar t1
left join Caltest t2 ON t1.CalendarDate = t2.TRANSDATE
where (t2.TRANSDATE IS NULL)
and CalendarDate < getdate()
and CalendarDate >= (select min(TransDate) from Caltest )
I recommend hard coding the date ranges instead of using the sub query as it is a performance problem otherwise. I also assume you don't have transactions greater than today.
You can also create a Calendar table just for the min-max date ranges and join to that to avoid the < or >= comparisons in the query.
Thank you all for your help.
Here is the query that worked for me:
SELECT B.CalendarDate, A.TransDate
FROM Calendar AS B
left outer JOIN CalTest AS A ON A.TransDate = B.CalendarDate
where A.TransDate IS NULL and B.CalendarDate between '4/1/2015' and '4/10/2015'
Order By b.CalendarDate
thanks again for your help

Left Outer Join and simple join within 3 tables

I am new to queries so excuse my ignorance.
The temp table #all has three columns: cod, cust_name, end_date. This table has 2500 rows. When the below query is run, I am not getting all the codes but it gives me about 400 rows.
For the HCS_Dtl and HCIS_Hd table: there will always be one matching row in both
SELECT p.cod, count(d.FormNo), SUM(d.NetAmt)
FROM #all p left outer join HCS_Dtl d on p.cod=d.Code
join HCIS_Hd h on d.FormNo=h.FormNo
WHERE
h.TimeStmp between '2015-03-01 00:00:00' and '2015-03-28 23:59:59'
GROUP BY p.cod
I need that I get those 2500 rows from #all even they don't have a form during this time period that I am mentioning in where clause of the query. How could it be possible?
I am using SQL Server 2008 R2
Try using LEFT JOIN on table HCIS_Hd
SELECT p.cod, count(d.FormNo), SUM(d.NetAmt)
FROM #all p left outer join HCS_Dtl d on p.cod=d.Code
LEFT JOIN HCIS_Hd h on d.FormNo=h.FormNo
WHERE
h.TimeStmp between '2015-03-01 00:00:00' and '2015-03-28 23:59:59'
GROUP BY p.cod

Resources