Suppose I have the following table:
CustomerId
Amount
Date
LastMonthDate
SumLastMonthAmount
1
500
20220301
20220201
500
1
200
20220304
20220204
700
1
400
20220320
20220220
1100
1
100
20220329
20220229
1200
1
100
20220402
20220302
800
As you can see, I want to have sum of amount for last month; suppose that SumLastMonth is NULL in the table, how should I update this column?
Note that you can't use date functions at all. and our date columns have int type as you see
The query that I wrote for this task is:
UPDATE A
SET SumLastMonthAmount = (SELECT SUM(Amount)
FROM Table B
WHERE A.CustomerId = B.CustomerId
AND B.Date > A.LastMonthDate
AND B.Date <= A.Date)
FROM Table A
Where A.Date=20220402
But it is very slow. Can you suggest a better query?
your code is modified as below. if last month is not identified "last Month amount" will be null
with cte as(
select A.CustomerId , A.LastMonthDate, A.Date,SUM(B.Amount) as newLastMonthAmount
from Table A
left Join Table B
on A.CustomerId = B.CustomerId
AND B.Date > A.LastMonthDate
AND B.Date <= A.Date
group by A.CustomerId , A.LastMonthDate, A.Date
)
update A
set SumLastMonthAmount=B.newLastMonthAmount
from Table A
join cte B
on A.CustomerId = B.CustomerId
AND B.Date = A.Date
AND B.LastMonthDate = A.LastMonthDate
Related
I'm trying to get data into datatables (js library for data table) by server-side processing.
The data should be produced as below
+---------+--------+--------+
| Name | TotalA | TotalB |
+---------+--------+--------+
| Person1 | 10 | 40 |
+---------+--------+--------+
The query that I tried
select
a.Name,
(select count(*) from SummaryA where id = a.id) as TotalA,
(select count(*) from SummaryB where id = a.id) as TotalB
from
records a
order by
a.Name
offset 0 rows fetch next 10 rows only
and
select
aa.Name,
(select count(*) from SummaryA where id = aa.id) as TotalA,
(select count(*) from SummaryB where id = aa.id) as TotalB
from
(select
a.Name, a.id
from
records a
order by
a.Name
offset 0 rows fetch next 10 rows only) as aa
However, these queries will result in an error as below
Error in query: Invalid usage of the option NEXT in the FETCH statement.
Running below query is not a problem
select
a.Name
from
records a
offset 0 rows fetch next 10 rows only
Issue- offset_row_count_expression can be a variable, parameter, or constant scalar subquery. When a subquery is used, it cannot reference any columns defined in the outer query scope.
link
Try
;with temp as (select a.name ,
count(b.id) as TotalA ,
count(c.id) as Totalb
FROM records a
left join SummaryA b
b.id=a.id
left join SummaryB c
c.id=a.id
group by a.name)
select * from temp
order by temp.Name
Offset 0 rows
fetch next 10 rows only
This can also be solved
with tmp as (
select a.name ,
a.id
FROM records a
order by temp.Name
Offset 0 rows
fetch next 10 rows only
)
select a.name ,
count(b.id) as TotalA ,
count(c.id) as Totalb
FROM tmp a
left join SummaryA b
b.id=a.id
left join SummaryB c
c.id=a.id
group by a.name order by a.Name
I have an employee table that need to join to staff time table to get staff time value on employee_id, date and interval in MS SQL.
If you look at the example below, you will notice that the id 2 and 3 have the same interval. In this case, I want the first value in the records which have the same employee_id, date and interval to have the actual staff time, and zero for the rest, even though all these records will have different ID.
Would you please show me how to achieve this? Thank you for your help everyone!
Employee Table
Staff Time
This is what I need:
This is what I have so far:
select a.*, b.staff_time
from employee a
left join staff_time b on
a.employee_id = b.Employee_ID
and a.date = b.date
and a.interval = b.interval
And above query produces this:
I am able to come up with query which gives me what I want but is there anyway to simplify it?
select a.id,a.employee_id,a.date,a.interval,a.Staff_Time,
case when a.rankk = 1 then a.Staff_Time else 0 end new_Staff_Time
from
(select a.*, b.staff_time,
ROW_NUMBER() over (partition by a.employee_id,a.date,a.interval order by a.date DESC) as rankk
from employee a
left join staff_time b on
a.employee_id = b.Employee_ID
and a.date = b.date
and a.interval = b.interval) a
left join
(
select a.*, b.staff_time
from employee a
left join staff_time b on
a.employee_id = b.Employee_ID
and a.date = b.date
and a.interval = b.interval
) b on a.id <> b.id and
a.employee_id = b.Employee_ID
and a.date = b.date
and a.interval = b.interval
I have two tables, Table A has a date field for every day of the year and a rate field for each of those days. Table B has a list of certain dates. How do I get the average of the rate field in Table A for the first date in Table B and the second date in Table B, then the average rate in Table A for the second date and the third date in Table B and so on and so forth.
Below is my attempt thus far.
Select Tran_Date, avg(rate)
From [dbo].[10_Year_TBill_Rates] a
left join #cashwithrn b
on a.observation_date = b.Tran_Date
where Tran_Date is null
group by Tran_date
You have to remove the row: where Tran_Date IS NULL:
SELECT Tran_Date, ISNULL(AVG(rate), 0)
FROM [dbo].[10_Year_TBill_Rates] a
LEFT JOIN #cashwithrn b
ON a.observation_date = b.Tran_Date
GROUP BY Tran_date
Since you're only average two numbers at any time, it might be easier to do something like this:
; With CTE as (Select b.date
, a.rate
, row_number() over (order by b.date) as RN
from TableB b
left join TableA a
on b.date = a.date)
Select a.date as Date1
, b.date as Date2
, (a.rate + b.rate)/2 as AverageRate from CTE a
left join CTE b
on a.rn + 1 = b.rn
Note that the row_number is unnecessary if you already have sequentially assigned IDs in your table.
The first part retrieves the rate for each of the dates in B, the second part connects that rate with the rate from the row immediately following it, and averages them.
Depending on your version of SQL Server, you might be able to simplify this with lag or lead. If you are uncomfortable with CTEs, you can apply the same logic using a temp table instead.
Can someone help me with this query? I want to get the result of all the customer_id which repeats more than once in 24hrs
SELECT
O.Order_No, O.Customer_ID, O.DateOrdered, O.IPAddress,
C.FirstName, C.LastName, CD.nameoncard
FROM
Order_No O
INNER JOIN
CardData CD ON O.card_id = CD.id
INNER JOIN
Customers C ON O.customer_id = C.customer_id
ORDER BY
O.order_no desc
adding more details..
so suppose order with customer id xx was placed on 04/23 2:30 pm and again 2nd order was placed with same customer Id xx on same day 04/23 5:30 pm.
i want the query to return me customer Id xx
Thanks
select Customer_ID, CAST(DateOrdered as Date) DateOrdered, count(*) QTDE
from Order_No
group by Customer_ID, CAST(DateOrdered as Date)
having count(*) > 1
To get the customers who have orders issued after the first one, then you could use the following query:
select distinct A.Customer_ID
from Order_No A
inner join (select Customer_ID, min(DateOrdered) DateOrdered from Order_No group by Customer_ID ) B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered - B.DateOrdered <= 1
and A.DateOrdered > B.DateOrdered
SQL Fiddle
To get all customers that have ANY TIME more than one order issued in period less or equal than 24h
select distinct A.Customer_ID
from Order_No A
inner join Order_No B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered > B.DateOrdered
and A.DateOrdered - B.DateOrdered <= 1
SQL Fiddle
Self-join:
SELECT distinct O.Customer_ID
FROM
Order_No O
inner join Order_No o2
on o.customerID = o2.customerID
and datediff(hour, o.DateOrdered, o2.DateOrdered) between 0 and 24
and o.Order_No <> o2.Order_No
This will return all customer_IDs that have ever placed more than one order in any 24 hour period.
Edited to add the join criteria that the matching records should not be the same record. Should return customers who placed two different orders at the same time, but not customers who placed only one order.
Have 2 tables TableA
StudentID MeetingID TeacherID Date
001 1002581 1056 10-12-2012
001 1006789 1056 10-13-2012
001 1006754 1058 10-13-1012
Have one more table B
StudentID MeetingID TeacherID Date Value
001 1002581 1056 10-12-201 15
001 1002856 1056 10-20-2012 21
The conditions are max(date) of a particular student teacher meeting from table A matches the max(date) of the same student teacher meeting in table B with the value. I would like to see the resultset as something like
StudentID MeetingID TeacherID Date Value
001 1006789 1056 10-20-2012 21
How can i achieve the above resultset
First, I'm curious why you have the same data in two separate tables instead of linking them via ID. I.e. Meetings -> Values
Per your requirements, this should work. This finds the most recent meeting which is present in both tables.
SELECT B.*
FROM B INNER JOIN A ON B.StudentID = A.StudentID AND B.MeetingID = A.MeetingID AND B.Date = A.Date
WHERE B.Date = (SELECT MAX(Date) FROM A WHERE A.StudentID = B.StudentID AND A.MeetingID = B.MeetingID)
Here's the Fiddle: http://sqlfiddle.com/#!6/d15ca/4
SELECT TOP 1 c.StudentID,c.MeetingID,c.TeacherID,c.tab1_dates,c.VALUE
FROM
(
SELECT a.StudentID,a.MeetingID,a.TeacherID,a.Dates AS tab1_dates,b.Dates AS tab2_dates,b.VALUE,
ROW_NUMBER() OVER (ORDER BY a.Dates,b.Dates) AS RN1
FROM tab2 b
INNER JOIN
(
SELECT StudentID,MeetingID,TeacherID,Dates FROM tab1
) a
ON b.StudentID = a.StudentID
AND b.TeacherID = a.TeacherID
) c
ORDER BY RN1 DESC
--SQL Fiddle - http://www.sqlfiddle.com/#!3/c6cea/1
Sorry, couldn't format well.