Create a view on multiple row conditions - sql

I have a Cycles table like this:
Value Name Month
10 P00006 201412
20 P00006 201501
30 P00006 201502
100 P00007 201509
200 P00007 201510
300 P00007 201511
I would like to create a view based on this table where for each Name I sum the values of the previous months.
This the expected result :
AccruedValue Name Month
10 P00006 201412
30 P00006 201501
60 P00006 201502
100 P00007 201509
300 P00007 201510
600 P00007 201511
I am not sure this can be achieved without a using a cursor so any help will be appreciated.

Test data:
create table cycles
(value NUMBER, name VARCHAR2(250), month VARCHAR2(250));
/
INSERT INTO cycles VALUES(10 , 'P00006','201412');
INSERT INTO cycles VALUES(20 , 'P00006','201501');
INSERT INTO cycles VALUES(30 , 'P00006','201502');
INSERT INTO cycles VALUES(100 , 'P00007','201509');
INSERT INTO cycles VALUES(200 , 'P00007','201510');
INSERT INTO cycles VALUES(300 , 'P00007','201511');
View my_view:
create or replace view my_view as
select
sum(value) over (partition by name order by month ) as AccruedValue ,
name ,
month
from cycles;
Result:
select * from v;
10 P00006 201412
30 P00006 201501
60 P00006 201502
100 P00007 201509
300 P00007 201510
600 P00007 201511

Related

Access SQL Query to Count Unique Occurrences of One Field Matching Multiple Parameters/Rows, Some Identical

Struggling with ms-access's flavor of SQL queries still, though I've made some progress (thanks to y'all). I have an event log table like this:
Logs Table
logID (auto#)
modID (str)
relID (str)
DateTime (date)
TxType (short)
1
1234
22.3
10/1/22 0800
6
2
1234
22.3
10/1/22 0900
7
3
1234
22.3
10/1/22 1000
13
4
1234
22.3
10/1/22 1100
15
5
4321
22.3
10/1/22 0830
1
6
4321
22.3
10/1/22 0930
13
7
4321
22.3
10/1/22 1030
15
8
4321
22.3
10/1/22 1130
13
9
1234
23.1
11/1/22 0800
1
10
1234
23.1
11/1/22 0900
15
11
1234
23.1
11/1/22 1000
13
12
1234
23.1
11/1/22 1100
15
13
4321
23.1
11/1/22 0830
13
14
4321
23.1
11/1/22 0930
7
15
4321
23.1
11/1/22 1030
13
16
4321
23.1
11/1/22 1130
15
What I need to do is:
filter the table by relID, then
count the number of modID's that have a 15 txType as the last/most recent chronological event in their rows.
So ideally I'd filter e.g. by relID=23.1 and get these results (but not logID # 10 for example) and then count them:
logID (auto#)
modID (str)
relID (str)
DateTime (date)
TxType (short)
12
1234
23.1
11/1/22 1100
15
16
4321
23.1
11/1/22 1130
15
As part of another function I have been able to count any modID's having a single txType successfully using
SELECT COUNT(*)
FROM (
SELECT DISTINCT Logs.modID, Logs.relID
FROM Logs
WHERE ((Logs.relID='23.1') AND ((Logs.TxType=13)))
);
Another stackoverflow user (exception - thanks!) showed me how to get the last event type for a given modID, relID combination using
SELECT TOP 1 TxType
FROM Logs
WHERE (((Logs.modID=[EnterModID])) AND ((Logs.relID=[EnterRelID])))
ORDER BY DateTime DESC;
But I'm having trouble combining these two. I know I can combine COUNT and GROUP BY but Access treats GROUP BY very particularly, and I'm not sure how to use SELECT TOP to get the latest events for each modID rather than just the latest events in the table, period.
This should give you the logID from the row with the latest DateTime for each combination of modIDand your target relID:
PARAMETERS which_relID Text(255);
SELECT DISTINCT
(
SELECT TOP 1 logID
FROM Logs
WHERE modID=l.modID AND relID=l.relID
ORDER BY [DateTime] DESC
) AS latest_modID
FROM Logs AS l
WHERE l.relID=[which_relID]
Use it as a subquery which you INNER JOIN to your Logs table. Note the subquery evaluates rows regardless of TxType. So have the parent query select only rows whose TxType = 15
PARAMETERS which_relID Text(255);
SELECT l2.*
FROM
Logs AS l2
INNER JOIN
(
SELECT DISTINCT
(
SELECT TOP 1 logID
FROM Logs
WHERE modID=l.modID AND relID=l.relID
ORDER BY [DateTime] DESC
) AS latest_modID
FROM Logs AS l
WHERE l.relID=[which_relID]
) AS sub
ON l2.logID=sub.latest_modID
WHERE l2.TxType=15;
Note I moved the PARAMETERS clause into the parent query. But you can eliminate it altogether if you believe it's causing trouble.
DateTime is a reserved word. I enclosed it in square brackets to ensure Access understands we mean the name of an object.
Using your sample data, I get these 2 rows when I supply 23.1 for the query parameter:
logID
modID
relID
DateTime
TxType
12
1234
23.1
11/1/2022 11:00:00 AM
15
16
4321
23.1
11/1/2022 11:30:00 AM
15
I get a single row with 22.3 for the parameter:
logID
modID
relID
DateTime
TxType
4
1234
22.3
10/1/2022 11:00:00 AM
15

Sales amounts of the top n selling vendors by month with other fields in bigquery

i have a table in bigquery like this (260000 rows):
vendor date item_price discount_price
x 2021-07-08 23:41:10 451,5 0
y 2021-06-14 10:22:10 41,7 0
z 2020-01-03 13:41:12 74 4
s 2020-04-12 01:14:58 88 12
....
exactly what I want is to group this data by month and find the sum of the sales of only the top 20 vendors in that month. Expected output:
month vendor_name(top20) sum_of_vendor's_sales sum_of_vendor's_discount item_count(sold)
2020-01 x1 10857 250 150
2020-01 x2 9685 410 50
2020-01 x3 3574 140 45
....
2021 01 x20 700 15 20
2020-02 y1 7421 280 120
2020-02 y2 6500 250 40
2020-02 y3 4500 200 70
.....
2020-02 y20 900 70 30
i tried this (source here). But The desired output could not be obtained.
select month,
(select sum(sum) from t.top_20_vendors) as sum_of_only_top20_vendor_sales
from (
select
format_datetime('%Y%m', date) month,
approx_top_sum(vendor, item_price, 20) top_20_vendors,count(item_price) as count_of_items,sum(discount_price)
from my_table
group by month
) t
Consider below approach
select
format_datetime('%Y%m', date) month,
vendor as vendor_name_top20,
sum(item_price) as sum_of_vendor_sales,
sum(discount_price) as sum_of_vendor_discount,
count(*) as item_count_sold
from your_table
group by vendor, month
qualify row_number() over(partition by month order by sum_of_vendor_sales desc) <= 20

SQL first value by group

In a table like this
acc_id time approved_amount balance
11 Jan14 580 500
11 Feb14 580 400
11 Mar14 580 300
11 Apr14 580 200
22 Jan14 . 800
22 Feb14 . 700
22 Mar14 . 600
I want to create a column orig_amount that would be equal to approved_amount if this is not null and to the first value of balance - to balance at time = min(time) by acc_id if approved_amount is null.
Therefore the desired output would look like this:
acc_id time approved_amount balance orig_amount
11 Jan14 580 500 580
11 Feb14 580 400 580
11 Mar14 580 300 580
11 Apr14 580 200 580
22 Jan14 . 800 800
22 Feb14 . 700 800
22 Mar14 . 600 800
I have now this
create table second_table as
select *,
coalesce(approved_amount, case when time = min(time) then
balance end ) as orig_amount
from first_table
group by acc_id
order by acc_id, time;
But still not the desired result. Can anybody help please?
You can use the first_value() window function and coalesce().
SELECT acc_id,
time,
approved_amount,
balance,
coalesce(approved_amount,
first_value(balance) OVER (PARTITION BY acc_id
ORDER BY time)) orig_amount
FROM first_table;
db<>fiddle

How to insert into aonther SQL Server table

I have a table tblOriginal which looks like this (and has no primary key):
employeeId code amount date
-----------------------------
emp01 sbk 10000 201501
emp02 sbk 10002 201501
emp02 cka 2000 201501
emp03 sbk 10003 201501
emp04 sbk 10004 201501
emp01 sbk 20000 201502
emp01 dgr 5000 201502
emp02 sbk 20002 201501
emp02 qaw 2000 201502
emp02 dng 4000 201502
emp03 sbk 20003 201502
emp04 sbk 20004 201502
What I need to do get all data with the code sbk into a table named tblEmp (employeeId is the primary key) to look as follows:
employeeId code amount date amount2 date2
----------------------------------------------
emp01 sbk 10000 201501 20000 201502
emp02 sbk 10002 201501 20002 201501
emp03 sbk 10003 201501 20003 201502
emp04 sbk 10004 201501 20004 201502
And then get the remaining data into another table named tblOthers to look as follows. Primary key is also employeeId
employeeId code amount date code2 amount2 date2
--------------------------------------------------
emp02 cka 2000 201501
emp01 dgr 5000 201502
emp02 qaw 2000 201502 dng 4000 201502
My problem is I don't know how to take data which has the same name into a employeeId into the tables and store the data into the columns
Any help will be appreciate.
All tables have been created
if there is absolutely 2 amount you can use some thing like this for the other table
;with temp as (
select empemployeeId,
lag(amount,1,null) over (partition by empemployeeId ORDER BY date ASC) as amount,
lag(date,1,null) over (partition by empemployeeId ORDER BY date ASC) as date,
lag(amount,1,null) over (partition by empemployeeId ORDER BY date DESC) as amount2,
lag(date,1,null) over (partition by empemployeeId ORDER BY date DESC) as date2,
from tblOriginal
)
select empemployeeId,'sdk',amount,date,amount2,date2 into tblEmp from temp to
where to.code='sdk'
Please refer this link :
http://www.w3schools.com/sql/sql_and_or.asp
SQL AND & OR operators are used to filter records based on more than one condition.
AND Operator Example -
SELECT * FROM Customers WHERE Country='Germany' AND City='Berlin';
OR Operator Example -
SELECT * FROM Customers WHERE City='Berlin' OR City='München';
Combining AND & OR -
SELECT * FROM Customers WHERE Country='Germany' AND (City='Berlin' OR City='München');

Calculate wrong amount in query

I have a table with some records now want to repeat this table content with some logic. I have two date start date and termination date, means record start from start_date and end on termination date, it will working fine but problem is calculate amount on it,
Logic is amount calculation formula
basesalary / 12 * ( SUTARate / 100 ) * ( x.num+1)
if this amount is less than SUTAMaximumAmount this amount is used, else 0. And one more thing if amount will be remain and year is complete then restart calculation from next year.. x.num is temporary table which hold 90 number from 1 to 90
Table
BaseSalary| S_Date | T_Date | SUTARate| SUTAMaximumAmount |A_S_Percent
48000 | 7-1-2013 | 3-15-2015 | 1.1 | 300 | 5
My result is
DAte amount
2013-07-01 00:00:00.000 44
2013-08-01 00:00:00.000 44
2013-09-01 00:00:00.000 44
2013-10-01 00:00:00.000 44
2013-11-01 00:00:00.000 44
2013-12-01 00:00:00.000 44
2014-01-01 00:00:00.000 36
2014-02-01 00:00:00.000 -8
2014-03-01 00:00:00.000 -52
2014-04-01 00:00:00.000 -96
2014-05-01 00:00:00.000 -140
2014-06-01 00:00:00.000 -184
2014-07-01 00:00:00.000 -228
2014-08-01 00:00:00.000 -272
2014-09-01 00:00:00.000 -316
2014-10-01 00:00:00.000 -360
2014-11-01 00:00:00.000 -404
2014-12-01 00:00:00.000 -448
2015-01-01 00:00:00.000 -492
2015-02-01 00:00:00.000 -536
2015-03-01 00:00:00.000 -580
and I want result like this
Date | Amount
7-1-2013 44
8-1-2013 44
9-1-2013 44
10-1-2013 44
11-1-2013 44
12-1-2013 44
1-1-2014 44
2-1-2014 44
3-1-2014 44
4-1-2014 44
5-1-2014 44
6-1-2014 44
7-1-2014 36
1-1-2015 44
2-1-2015 44
3-1-2015 44
Query
SELECT dateadd(M, (x.num),d.StartDate) AS TheDate,
Round( case when ((convert(float,d.SUTARate)/100* convert(integer,d.BaseSalary) / 12)*(x.num+1)) <=CONVERT(money,d.SUTAMaximumAmount)
then (convert(float,d.SUTARate)/100* convert(integer,d.BaseSalary)* / 12)
else (CONVERT(money,d.SUTAMaximumAmount)-((convert(float,d.SUTARate)/100* (convert(integer,d.BaseSalary) / 12)*x.num)))*Power((1+convert(float,d.AnnualSalaryIncreasePercent)/100),Convert(int,x.num/12)) end, 2) AS Amount,
FROM #Table AS x, myTbl AS d
WHERE (x.num >= 0) AND (x.num <= (DateDiff(M, d.StartDate, d.TerminationDate)) )
temporary table
create TABLE #Table (
num int NOT NULL,
);
;WITH Nbrs ( n ) AS (
SELECT 0 UNION ALL
SELECT 1 + n FROM Nbrs WHERE n < 99 )
INSERT #Table(num)
SELECT n FROM Nbrs
OPTION ( MAXRECURSION 99 )
this table used as x in above query
I created this SQLFiddle.
-- Numbers table is probably a good idea
WITH Nbrs ( num ) AS
(
SELECT 0 UNION ALL
SELECT 1 + num FROM Nbrs WHERE num < 99
)
-- All columns, except for 'num' come from myTbl
SELECT dateadd(M, (num),S_Date) AS TheDate,
Round(
CASE
WHEN (SUTARate / 100) * (BaseSalary / 12) <= SUTAMaximumAmount
THEN (SUTARate / 100) * (BaseSalary / 12)
ELSE 0
END
, 2) As Amount
-- This may be the number you were trying to multiply
,DatePart(Month, dateadd(M, (num),S_Date)) As PotentialMultiiplier
FROM Nbrs AS x, myTbl AS d
WHERE (num >= 0)
AND (num <= (DateDiff(M, S_Date, T_Date)) )
I am not entirely sure what your goal is, but you are probably on the right track with a numbers table. Because the result you are going for does not change much over time (i.e., nearly every month has an amount of $44), it is difficult to determine the correct code for the query. So, I recommend you provide a different set of data for better result-checking.
If you fiddle with the SQL in the provided link, you can re-post with better code, and then we can better solve your issue.