I have a table with two Date columns. DATE1 is sometimes NULL and sometimes contains duplicate values. DATE2 is always populated and unique. My table is sorted by latest DATE2 date.
I'd like to create a new date column where DATE1 will be selected unless its value is duplicated from the next row or it's NULL. In this case, I want to take the value of DATE2. I also need two boolean columns that tell me when either of those conditions were met. Let me demonstrate using an example so it's clearer.
In the table below, row 5 and 6 have a value of Jul 27, 2011 so I'd like to set the new date column of row 5 to Aug 4, 2011 (which is DATE2). In row 3, the value of DATE1 is NULL so I want to take the value of DATE2.
I've tried a few inner select statements but can't get this to work. Any ideas?
My table as it currently stands in the database:
Row DATE1 DATE2
--------------------------------------
1 Oct 10, 2011 Nov 13, 2011
2 Oct 10, 2011 Oct 10, 2011
3 NULL Oct 8, 2011
4 Aug 12, 2011 Aug 12, 2011
5 Jul 27, 2011 Aug 4, 2011
6 Jul 27, 2011 Jul 28, 2011
7 Jul 1, 2011 Jul 26, 2011
8 May 24, 2011 Jun 13, 2011
What I expect the final result to look like:
Row FINAL_DATE DATE1_DUPLICATE DATE1_WAS_NULL
----------------------------------------------------------
1 Nov 13, 2011 TRUE FALSE
2 Oct 10, 2011 FALSE FALSE
3 Oct 8, 2011 FALSE TRUE
4 Aug 12, 2011 FALSE FALSE
5 Aug 4, 2011 TRUE FALSE
6 Jul 27, 2011 FALSE FALSE
7 Jul 1, 2011 FALSE FALSE
8 May 24, 2011 FALSE FALSE
Thanks so much!
This can be handled with sequential scanning of the table and using MySQL variables. You can test in (updated) SQL-fiddle:
SELECT date2
, dd
, DATE_FORMAT(dd, '%b %e, %Y') AS final_date
, date1_duplicate
, date1_was_null
FROM
( SELECT date2
, COALESCE( (date1 = #d OR date1 = #prev), FALSE)
AS date1_duplicate
, (date1 IS NULL) AS date1_was_null
, #d := CASE WHEN (date1 = #d OR date1 = #prev)
THEN date2
ELSE COALESCE(date1, date2)
END AS dd
, #prev := date1 AS pre
FROM tableX AS t
CROSS JOIN
( SELECT #d := DATE('1000-01-01')
, #prev := #d
) AS dummy
ORDER BY date2 ASC
) AS tmp
ORDER BY date2 DESC
;
Related
I have a table with this data :
id quantity month year
1 10 12 2020
2 78 3 2019
3 67 4 2020
4 78 3 2020
5 56 2 2020
6 34 4 2017
7 56 2 2017
I want to get all data's from 2017, month 3 till 2020 month 3
My sql look like :
where (dc.year >= 2017 and dc.month >= 3) and (dc.year <= 2020 and dc.month <= 3)
GROUP BY dc.year, dc.month
this sql get only data for 2017,3 and 2018, 3 and 2019,3 and 2020,3
But I need the whole interval. If I put
where dc.year >= 2017 and dc.year <= 2020
GROUP BY dc.year, dc.month
Getting all datas but I need data from 2017 month 3 -----> 2020 month 3 (all interval)
One method uses arithmetic:
where dc.year * 12 + dc.month between 2017 * 12 + 3 and 2020 * 12 + 3
Alternative, you can use a more complex expression:
where (dc.year = 2017 and dc.month >= 3) or
(dc.year > 2017 and dc.year < 2020) or
(dc.year = 202 and dc.month <= 3)
You could simply build dates from these numbers and use them for comparison. I think that it makes the intent clearer, and really is in the spirit of your logic (which is to filter by date):
In SQL Server:
where datefromparts(year, month, 1) between '2017-03-01' and '2020-03-01'
In MySQL:
where concat_ws('-', year, month, 1) between '2017-03-01' and '2020-03-01'
I have a payments table, Where I update the subscription renewal date and amount, now I have a query to select previous 13 months sum of amounts column, But how do I add zero if no payment data is available for any month in the selected last 13 months of record.
SELECT DATE_FORMAT(dtSubscriptionRenewalDate, "%b - %Y") AS month, SUM(intPaymentAmount) as usd13mon FROM `tbl_pi_payment` WHERE strCurrencyCode = 'USD' and dtSubscriptionRenewalDate <= NOW() and dtSubscriptionRenewalDate >= Date_add(Now(),interval - 13 month) GROUP BY DATE_FORMAT(dtSubscriptionRenewalDate, "%Y-%m")
month usd13mon
Oct - 2018 55
Dec - 2018 79
Jan - 2019 16
Feb - 2019 93
Mar - 2019 80
Apr - 2019 83
May - 2019 34
Jun - 2019 23
Jul - 2019 25
Aug - 2019 37
Sep - 2019 17
Oct - 2019 44
In the above-mentioned output the nov 2018 month is missing as there was data available in the table.
You may try introducing a calendar table which represents every month which you want to appear in your report:
SELECT
m.my,
COALESCE(SUM(t.intPaymentAmount), 0) AS usd13mon
FROM
(
SELECT 'Nov - 2018' AS my UNION ALL
SELECT 'Dec - 2018' UNION ALL
SELECT 'Jan - 2019' UNION ALL
...
SELECT 'Nov - 2019'
) m
LEFT JOIN tbl_pi_payment t
ON m.my = DATE_FORMAT(t.dtSubscriptionRenewalDate, '%b - %Y') AND
t.strCurrencyCode = 'USD' AND
t.dtSubscriptionRenewalDate BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL - 13 MONTH)
GROUP BY
m.my;
my table person like:
id, bron_year, file_date
2, 1943, 2010
5, 1952, 2017
7, 1953, 2018
8, 1952, 2018
9, 1954, 2017
Here the file_date means the file of person's create date, and file_date >= 2009.
And I create a procedure like:
CREATE OR REPLACE PROCEDURE `aged_person`()
BEGIN
DECLARE c_year int;
SET c_year = 2009;
WHILE c_year < YEAR(CURDATE()) DO
SELECT * FROM `person` WHERE YEAR(`file_date`) = c_year AND c_year - `bron_year` >= 65 ORDER BY `file_date` ASC, `id` ASC;
SET c_year = c_year + 1;
END WHILE;
END;
It means in every year, collect the aged person (in that year, person's age >= 65).
Now I want union all the results, and must keep the order. How to do that please?
BTW, I do not want create a temp table, because some person will be out (moving house, missing visit), then the person will not in table.
Example:
If c_year = 2018, the results (keep order):
2, 1943, 2010
5, 1952, 2017
8, 1952, 2018
7, 1953, 2018
If c_year = 2019, the results (keep order):
2, 1943, 2010
5, 1952, 2017
8, 1952, 2018
7, 1953, 2018
9, 1954, 2017
Simple query, and no stored procedures:
SELECT *
FROM person
WHERE file_date >= 2009
AND (file_date - bron_year) >= 65
ORDER BY file_date ASC, id ASC
Hi i have a table like below
year | month | otherdata
2015 1
2015 1
2015 3
2015 4
2015 4
2016 1
2016 2
2016 2
here how do i select all data of (year 2015/month 4 to year 2016/month 2)
i tried following query.
select * from `schedule_details` where (`year` >= 2015 and `month` >= 4) and (`year` <= 2016 and `month` >= 2)
but its not working. how do i do this? please help
thanks
Solved the problem
Select *
From schedule_details
Where ( year = 2015 And month >= 4 )
Or ( year > 2015 And year < 2016 )
Or ( year = 2016 And month <= 2 )
is there any other better way?
Can anyone assist in a sql statement I am trying to write? I'm using SSRS r1 (either sql or ssrs solution is fine)
How do I:
show count measure split by month and year
for each of those months, I want to count the previous cumulative 12 months
e.g.
2012 jan: counts feb 2011 - jan 2012
2012 feb: counts mar 2011 - feb 2012
2012 mar: counts apr 2011 - mar 2012
I have started this code but it's incorrect, however it gives you an idea of what I am trying to achieve (this issue is I have to calc month and year from a date)
select
count(a.measure) count
,month(a.StartDate)
,year(a.StartDate)
from
a
where
a.StartDate >= DATEADD(mm,DATEDIFF(mm,0,#datepromt)-12,0) as startdateYrAgo --1st month 1 year ago 01/01/2012
and a.StartDate <= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#datepromt)+1,0)) as startdateEOM --last day of month 31/01/2013
group by
month(a.StartDate)
,year(a.StartDate)
Here you have an idea for the query, it have to look something like below;
SELECT
periods.year
,periods.month
,measures.cnt
FROM (
SELECT DISTINCT
year = YEAR(StartDate)
, month = MONTH(StartDate)
, month_running = DATEDIFF(mm, 0, StartDate)
FROM a
GROUP BY YEAR(StartDate), MONTH(StartDate), DATEDIFF(mm, 0, StartDate)
) periods
JOIN (
SELECT month_running = DATEDIFF(mm, 0, StartDate), cnt = COUNT(measure)
FROM a
GROUP BY DATEDIFF(mm, 0, StartDate)
) measures
ON measures.month_running BETWEEN periods.month_running - 12 AND periods.month_running - 1