If I execute this query I get the result below
SELECT Month_Name,
Count(SalesID) AS Toal
FROM Sales
Group by Month_Name
I have the following Result
Month_Name Toal
Apr-15 341
May-15 314
Jun-15 342
Jul-15 327
Aug-15 179
Sep-15 234
Oct-15 286
Nov-15 171
PROBLEM: In previous month I have data for Feb-15 and Mar-15 but they are not on the table. I have been told not to update the table with the figures
I was given for Feb-15 and Mar-15. The figures are as follows
Feb-15 = 349
Mar-15 = 312
Is there a way I can write a query to reflect both months by hardcoding it in the query so that the result will look like the table below
Month_Name Toal
Feb-15 349
Mar-15 312
Apr-15 341
May-15 314
Jun-15 342
Jul-15 327
Aug-15 179
Sep-15 234
Oct-15 286
Nov-15 171
(
SELECT
Month_Name,
Count(SalesID) AS Toal
FROM
Sales
Group by
Month_Name
)
UNION ALL
(
SELECT
'Feb-15' AS Month_Name,
349 AS Total
)
UNION ALL
(
SELECT
'Mar-15' AS Month_Name,
312 AS Total
)
You'd add the two records with UNION ALL. In order to produce such records, you simply select them without a table or from DUAL - which of the two depends on the DBMS you are using.
As you certainly want the records to be sorted by month, there must be a sort key in your table to make this possible. In the following query I assume it to be a positive numeric value named sortkey and the two months to come first. Adjust this according to your needs.
select month_name, total
from
(
select month_name, count(*) as total, sortkey from sales group by month_name
union all
select 'Feb-15', 349, -2 -- here you may have to add FROM DUAL
union all
select 'Mar-15', 312, -1 -- here too
) all_months
order by sortkey;
Related
I am new to SQL and am facing this challenge where I need to take the scores of IDs based on 2 month old record respectively. To put it in simple demo:
APP Date
ID
Score 1
Score 2
Score 3
2022-10-31
121
254
312
789
2022-09-30
121
261
542
774
2022-08-31
121
424
432
786
2022-07-30
121
322
764
963
I applied the max function to return the scores based on max APP Date but can't seem to figure out a way to return records that are 2 months old. Based on today's date (November 07) I am expecting to see the below result:
APP Date
ID
Score 1
Score 2
Score 3
2022-09-30
121
261
542
774
Note: All APP Dates are based on month end.
Could anyone please guide me with this? Thanks in advance all!
Query I have used (until now):
with maxdate as (
select ID, max([APP_DATE]) as maxdate
from [Table]
where ID is not null group by ID
)
SELECT [APP_DATE],
a.ID,
Score 1,
Score 2,
Score 3
FROM [Table] a
join maxdate md on a.ID = md.ID and maxdate = a.[APP_DATE]
ORDER BY ID
may be below query help you.:
SELECT top 1 * FROM score
WHERE appdate <= DATEADD(month, -1, GETDATE())
order by appdate desc
Hi I would like to make a select expression using case or if/else which seems to be a simple solution from logic perspective but I can't seem to get it to work. Basically I am joining against two table here, the first table is customer record with date filter called min_del_date and then the second table for the model scoring table with BIN and update_date parameters.
There are two logics I want to display
Picking the model score that was the month before min_del_date
If model score month before delivery is greater than 50 (Bin > 50) then pick the model score for same month as min_del_date
My 1st logic code is below
with cust as (
select
distinct cust_no, max(del_date) as del_date, min(del_date) as min_del_date, (EXTRACT(YEAR FROM min(del_date)) -1900)*12 + EXTRACT(MONTH FROM min(del_date)) AS upd_seq
from customer.cust_history
group by 1
)
,model as (
select party_id, model_id, update_date, upd_seq, bin, var_data8, var_data2
from
(
select
party_id, update_date, bin, var_data8, var_data2,
(EXTRACT(YEAR FROM UPDATE_DATE) -1900)*12 + EXTRACT(MONTH FROM UPDATE_DATE) AS upd_seq,
dense_Rank() over (partition by (EXTRACT(YEAR FROM UPDATE_DATE) -1900)*12 + EXTRACT(MONTH FROM UPDATE_DATE) order by update_date desc) as rank1
from
(
select party_id,update_date, bin, var_data8, var_data2
from model.rpm_model
group by party_id,update_date, bin, var_data8, var_data2
) model
)model_final
where rank1 = 1
)
-- Add model scores
-- 1st logic Picking the model score that was the month before delivery date
select *
from
(
select cust.cust_no, cust.del_date, cust.min_del_date, model.upd_seq, model.bin
from cust
left join cust
on cust.cust_no = model.party_id
and cust.upd_seq = model.upd_seq + 1
)a
Now I am struggling in creating the 2nd logic in the same query?.. any assistance would be appreciated
cust table
cust_no
min_del_date
upd_seq
123
2021-01-11
1453
234
2020-06-29
1446
456
2020-07-20
1447
model table
party_id
update_date
upd_seq
BIN
123
2020-11-30
1451
22
123
2020-12-25
1452
54
123
2020-01-11
1453
14
234
2020-05-23
1445
76
234
2020-06-18
1446
48
234
2020-07-23
1447
12
456
2020-06-18
1446
23
456
2020-07-23
1447
39
456
2020-08-21
1448
21
desired results
cust_no
min_del_date
model.upd_seq
update_date
BIN
123
2021-01-11
1453
2020-01-11
14
234
2020-06-29
1446
2020-06-18
48
456
2020-07-20
1446
2020-06-18
23
Update
I managed to find the solution by myself, thanks for everyone who has attending this question. The solution is per below
select a.cust_no, a.del_date, a.min_del_date, b.update_date, b.upd_seq, b.bin
from
(
select cust.cust_no, cust.del_date, cust.min_del_date,
CASE WHEN model.BIN <=50 THEN model.upd_seq WHEN BIN > 50 THEN model.upd_seq +1 ELSE NULL END as upd_seq
from cust
inner join model
on cust.cust_no = model.party_id
and cust.upd_seq = model.upd_seq + 1
)a
inner join model b
on a.cust_no = b.party_id
and a.upd_seq = b.upd_seq
i would like to sum (purchase_prd) which is quarterly for customerID where purchase value is >0 and <=500. I have same customer ids in multiple purchase_prd, and would also like to see how many records show for their customerID....how do I query this?
I have the following
select purchase_prd, count(*), customerID, sum(purchase_value)
from table a
where purcahse_prd between 201700 and 201712 /*data is quarterly, so 201700, 201703, 201706,201709, 201712*/
group by customerid, purchase_value
having purchase_value >0 and purchase_value<=500
my results show customerids in multiple quarters and the sums of purchase_value exceeds 500, each quarter is separate and not extracting the total of purchase_value for the entire year with the criteria of purchase_value >0 and <=500
my results are:
purchase_prd customer ID purchase_value
201700 714 776
201703 714 120
201706 714 50
201709 714 20
201712 714 100
I'd like 2017 summed for customerID 714 and selected if sum of purchase_value is >0-<=500
I think you want:
select customerID, purchase_prd, count(*), sum(purchase_value)
from table a
where purchase_prd between 201700 and 201712 /*data is quarterly, so 201700, 201703, 201706,201709, 201712*/
group by customerid, purchase_prd
having sum(purchase_value) > 0 and sum(purchase_value) <= 500
I have a table with a few million entries, so I need a solution that can work on a bunch of different scenarios as most solutions I have found is only for a few iterations at best.
I have a PERIOD_FROM and a PERIOD_TO status check, aka how long the account has been in this state. It is no problem to split a two month difference but quite a few of the entries are for accounts that have paid in advance so their status will not change for up to 2 years.
The original table simplified looks something like this:
ID PERIOD_FROM PERIOD_TO DAYS
---------------------------------------------------------
115052454 02/04/2019 01/04/2021 730
115678935 06/04/2021 05/04/2023 729
119040627 06/04/2021 05/04/2023 729
115005487 01/04/2019 29/03/2021 728
116414279 17/04/2019 09/04/2021 723
116411046 17/04/2019 04/04/2021 718
116693271 24/04/2019 04/04/2021 711
123935704 05/07/2019 29/05/2021 694
119040627 16/05/2019 05/04/2021 690
115976183 02/05/2019 01/03/2021 669
What I have done for the two month difference solution is create a concat as follows:
CASE WHEN CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM')) = CONCAT(DATEPART(YYYY, [PERIOD_TO]), FORMAT([PERIOD_TO], 'MM'))
THEN CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM'))
ELSE CONCAT(DATEPART(YYYY, [PERIOD_FROM]), FORMAT([PERIOD_FROM], 'MM'), ',', DATEPART(YYYY, [PERIOD_TO]), FORMAT([PERIOD_TO], 'MM'))
END AS Period_Of
Using cross apply with string_split I can then split the line into two and using another case statement I can assign the full values based on if the period from/to is equal or greater than the split value, but this only works for a two month difference and I need up to 48 months.
I require an output that would look something like this:
ID PERIOD_FROM PERIOD_TO DAYS
------------------------------------------------------
1150524545 02/04/2019 30/04/2019 730
1150524545 01/05/2019 31/05/2019 730
1150524545 01/06/2019 30/06/2019 730
1150524545 01/07/2019 31/07/2019 730
………… ………… ………… ……
1150524545 01/02/2021 28/02/2021 730
1150524545 01/03/2021 31/03/2021 730
1150524545 01/04/2021 01/04/2021 730
Any help would be greatly appreciated!
UPDATE:
Thanks to the help of Serg, I have a solution. I tweaked it slightly so that the Period_To ends on the last date but had not specified that in my request as it was not a main concern.
Using table of numbers
-- Generate table of 1000 numbers starting 0
with t0(n) as (
select n
from (
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
) t(n)
),nmbs as(
select row_number() over(order by t1.n) - 1 n
from t0 t1, t0 t2, t0 t3
)
--
select Id
, dateadd(mm, nmbs.n, tbl.PERIOD_FROM) PERIOD_FROM
, case when ys.NextDate > tbl.PERIOD_TO then tbl.PERIOD_TO else ys.NextDate end PERIOD_TO
, DAYS
, tbl.PERIOD_TO originalPERIOD_TO
from [my table] tbl
join nmbs
on dateadd(mm, nmbs.n, tbl.PERIOD_FROM) <= tbl.PERIOD_TO
cross apply (select dateadd(mm, nmbs.n + 1, tbl.PERIOD_FROM) NextDate) ys
order by ID, dateadd(mm, nmbs.n, tbl.PERIOD_FROM);
Fiddle
I have a dataset which looks like this
id date
250 01-JAN-15
250 01-MAR-15
360 01-JUN-15
470 01-FEB-15
470 01-DEC-15
470 01-NOV-15
780 01-APR-15
790 01-SEP-15
790 01-MAY-15
I want to randomly select rows such that duplicated ids will appear only once. For example:
id date
250 01-MAR-15
360 01-JUN-15
470 01-FEB-15
780 01-APR-15
790 01-SEP-15
My current solution uses an analytic function, which takes a long time to run on hundreds of millions of rows:
select * from(
select aa.*, row_number() over (partition by id order by dbms_random.value) as random_flag
from table aa)
where random_flag = 1
Any tips on how to get the same result without analytic functions?
you can try this query:
SELECT id, (select t2.date from table t2 where t2.id = t1.id and rownum = 1)
FROM table t1
GROUP BY id;