Distribute table data to another table using SQL query - sql-server-2012

Help on how to distribute Default Table into Transaction Table using SQL Server Query if month is not existing on the other side? Please refer on the sample tables below
Default Table
Month
Value
Jan
0
Feb
0
Mar
0
Apr
0
May
0
Transaction Table
Month
Sales
Jan
10
Feb
0
Apr
20
I want to achieve this below results.
Month
Sales
Jan
10
Feb
0
Mar
0
Apr
20
May
0

You can use INSERT...WHERE NOT EXISTS
INSERT INTO Transaction (Month, Sales)
SELECT c.Month, d.Sales
FROM [Default] d
WHERE NOT EXISTS (SELECT 1
FROM Transaction t
WHERE t.Month = d.Month)

Related

SQL server multiple like query

I am trying to use multiple like query for column 1 and want show the data in seperate column, can I do
SELECT CONVERT(VARCHAR(100), DECRYPTBYKEY(ssr.optiontextresponse)) AS DueDate
FROM [dbo].[tblsubscribeReport] ssr
INNER JOIN [dbo].[tblsurveyque] sq on sq.surveyquestionid = CONVERT(VARCHAR(100), DECRYPTBYKEY(ssr.questionid)) --and [name] LIKE '%due%'
LEFT JOIN [dbo].[tblsurveyquestiono] so on so.surveyquestionoptionid = CONVERT(VARCHAR(100), DECRYPTBYKEY(ssr.optionid))
JOIN tblSubscribers s on s.SubscriberID = ssr.SubscriberId
WHERE
s.ClientID = '12'
and (sq.[name] LIKE '%due%' OR sq.[name] LIKE '%doc%' )
Due date
Feb 16, 2023
Shailesh Parihar
Feb 17 2023
Meet
Ank
feb 18 2023
Maria
Mar 2 2023
Mar 12 2023
Joun
Mar 11 2023
Smith
14/02/2023
Sarah
15-02-2023
Peggy
I Want show the my data in separate column

SQL: Find number of active "events" each month

Background
I have an SQL table that contains all events, with each event containing a unique identifier.
As you can see for some IDs the "event" stretches across multiple months. What I'm trying to find is the number of "active events" per month.
For example event ID:342, is active in both the month of Jan and Feb. So it should count towards both Jan and Feb's final count.
Example dataset
ID
Start Date
End Date
342
01 Jan 2022
12 Feb 2022
231
12 Feb 2022
26 Feb 2022
123
20 Jan 2022
10 Apr 2022
Desired output:
Month
Start Date
Jan
2
Feb
3
Mar
1
Apr
1
btw: I'm using Alibaba's ODPS SQL and not MySQL or Postgres. So i appreciate if the solution provided could be SQL system agnostic. Thanks!
Here is an example is MySQL 8, using a recursive CTE to construct the list of months. It would be more efficient to use a Calendar Table.
If you are not using MySQL you will need to modify the syntax of the query.
create table dataset(
ID int, Start_date Date,End_date Date);
insert into dataset values
(342,'2022-01-01','2022-02-12'),
(231,'2022-01-12','2022-02-26'),
(123,'2022-01-20','2022-04-10');
/*
Desired output:
Month Start Date
Jan 2
Feb 3
Mar 1
Apr 1
*/
✓
✓
✓
select
min(month(Start_date)),
max(month(End_date))
from dataset;
min(month(Start_date)) | max(month(End_date))
---------------------: | -------------------:
1 | 4
with recursive m as
(select min(month(Start_date)) mon from dataset
union all
select mon + 1 from m
where mon < (select max(month(End_date)) from dataset)
)
select
mon "month",
count(id) "Count"
from m
left join dataset
on month(Start_date)<= mon
and month(End_date) >= mon
group by mon
order by mon;
month | Count
----: | ----:
1 | 3
2 | 3
3 | 1
4 | 1
db<>fiddle here

Getting calculated percentages within group using SQL

I have a dataset:
Date
June 2011
July 2011
Aug 2011
Sep 2011
Oct 2011
Jan 2012
Feb 2012
Mar 2012
Apr 2013
May 2013
that records down the date registered for each yearly project. (There are no project IDs however)
I would like to add in the additional variable Percentage, which represent the average progress made for that month. (For instance, if the project is registered for 4 months, then each month would progress incrementally by 25 %, (25,50,75,100)), specifically:
Percentage Date
20 June 2011
40 July 2011
60 Aug 2011
80 Sep 2011
100 Oct 2011
33 Jan 2012
66 Feb 2012
100 Mar 2012
50 Apr 2013
100 May 2013
However, my main problem would be that I am unable to know the starting month (period) and ending month (period) for each project for each year.
Are there any functions in SQL to create the calculated percentages in this case? I thought of creating a year variable and further using an indicator to indicate the start/end of the progress, but could not move on further.
Thank you again!
You can try this query.
Getting ROW_NUMBER() by year(dates) on subquery.
then get the percent.
SELECT (FLOOR(CAST(T2.RK AS decimal) * 100/(
SELECT COUNT(1) AS Totle
FROM T
WHERE year(dates) = T2.dates))) [Percentage],
T2.dates as [years],
T2.months as [months]
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY year(dates) ORDER BY dates DESC) AS RK,
year(dates) as dates,
month(dates) as months
FROM T
) AS T2
GROUP BY T2.dates,T2.RK,T2.months
Here is a simple Pseudo sql to get what you want . ?
select Year(date), Month(date) ,
(select sum(Progress_percentage) from dataset b where b.date <=a.date ) as
subquery_percentage
from dataset a
group by Year(date), Month(date)

SUM and Count in one SQL Query

I have this kind of data
time Members
-------------------------------------------------- -----------
Jun 23 2016 1
Jun 23 2016 1
Jun 23 2016 2
Jun 29 2016 6
Jul 11 2016 3
Jul 11 2016 1
Jul 13 2016 1
I obtained this data using this sql query
SELECT CONVERT (VARCHAR(12), a.registered_time), COUNT(b.member_id) AS Members
FROM b
Inner JOIN a ON b.mirror_id = a.mirror_id
GROUP BY
(a.registered_time) order by a.registered_time
I want to get the sum of total numbers if they are of the same date for exampple the date of June 23 2016 will have total members of 4 and so on. Is it possible to have SUM() FUnction on Count()? How can I do this?
Convert the value to a date and include that in both the select and group by:
SELECT CONVERT(date, a.registered_time) as dte, COUNT(b.member_id) AS Members
FROM b JOIN
a
ON b.mirror_id = a.mirror_id
GROUP BY CONVERT(date, a.registered_time)
ORDER BY CONVERT(date, a.registered_time);

Select Every Date for Date Range and Insert

Using SQL Server 2008
I have a table A which has start date, end date and value. For each date within the start date and end date in Table A, I need to insert (or update if already exists) that date in table B such that the value in this table is value in A/DateDiff(Day,StartDate of A,EndDate of A).
Example:
Table A
ID StartDate EndDate Value
1 01 Jan 2014 03 Jan 2014 33
2 01 Feb 2014 02 Feb 2014 20
3 02 Jan 2014 03 Jan 2014 10
Table B
ID Date Value
1 01 Jan 2014 11
2 02 Jan 2014 16
3 03 Jan 2014 16
4 01 Feb 2014 10
5 02 Feb 2014 10
The way values are computed are - For ID 1, there are 3 days which means 11 units per day. So 1st, 2nd, 3rd Jan all get 11 units. Then because there are additional units with date range 2nd Jan to 3rd Jan which amount to 5 units per day, 2nd and 3rd Jan will be (11+5) 16. 1st and 2nd Feb just have one record so they will simply be 20/2 = 10.
I can think of a solution using loops, but want to avoid it entirely.
Is there any way I can achieve this through a set based solution? It is important for me to do this in bulk using set based approach.
I am trying to read through various articles and seems like CTE, Calendar Table or Tally Table might help but the examples I have seen require setting variables and passing start date and end date which I think will work for single record but not when doing all records at a time. Please suggest.
Thanks!
I think this should do it (DEMO):
;with cte as (
select
id
,startdate
,enddate
,value / (1+datediff(day, startdate, enddate)) as value
,startdate as date
from units
union all
select id, startdate, enddate, value, date+1 as date
from cte
where date < enddate
)
select
row_number() over (order by date) as ID
,date
,sum(value) as value
from cte
group by date
The idea is to use a Recursive CTE to explode the date ranges into one record per day. Also, the logic of value / (1+datediff(day, startdate, enddate)) distributes the total value evenly over the number of days in each range. Finally, we group by day and sum together all the values corresponding to that day to get the output:
| ID | DATE | VALUE |
|----|---------------------------------|-------|
| 1 | January, 01 2014 00:00:00+0000 | 11 |
| 2 | January, 02 2014 00:00:00+0000 | 16 |
| 3 | January, 03 2014 00:00:00+0000 | 16 |
| 4 | February, 01 2014 00:00:00+0000 | 10 |
| 5 | February, 02 2014 00:00:00+0000 | 10 |
From here you can join with your result table (Table B) by date, and update/insert the value as needed. That logic might look something like this (test it first of course before running in production!):
update B set B.VALUE = R.VALUE from TableB B join Result R on B.DATE = R.DATE
insert TableB (DATE, VALUE)
select DATE, VALUE from Result R where R.DATE not in (select DATE from TableB)