mysql -get data who complete within a year - mysql

I need to get date who finish within 1 year from a project . my project table contain 'Sdate ' and 'Edate' which I can I need to use it to find data who finish within 1 year how do I get data within a year. For example I need to get data who have finish the project within 1 year (different is within 1 year)
This is what I have tried
SELECT
concat(FName, ' ', LName) AS NAME
FROM
Employee
WHERE
EXISTS (
SELECT
DATE_SUB(Sdate, INTERVAL 1 YEAR) AS DIFF
FROM
Project
);

You can change the joined field based on your table column name and try below query -
SELECT
concat(e.FName, ' ', e.LName) AS NAME
FROM
Employee e
JOIN project p ON e.employeeId = p.employeeId
WHERE
p.Sdate >= DATE_SUB(p.Edate, INTERVAL 1 YEAR)
GROUP BY
e.id;
If you want to use exists function then use below query-
select concat(e.FName , ' ' , e.LName) as name
From Employee e
where exists(select * from product p where e.employeeId=p.employeeId and p.Sdate >= DATE_SUB(p.Edate,INTERVAL 1 YEAR)) group by e.id;

Related

Getting the number of users for this year and last year in SQL

My table is like this:
root_tstamp
userId
2022-01-26T00:13:24.725+00:00
d2212
2022-01-26T00:13:24.669+00:00
ad323
2022-01-26T00:13:24.629+00:00
adfae
2022-01-26T00:13:24.573+00:00
adfa3
2022-01-26T00:13:24.552+00:00
adfef
...
...
2021-01-26T00:12:24.725+00:00
d2212
2021-01-26T00:15:24.669+00:00
daddfe
2021-01-26T00:14:24.629+00:00
adfda
2021-01-26T00:12:24.573+00:00
466eff
2021-01-26T00:12:24.552+00:00
adfafe
I want to get the number of users in the current year and in previous year like below using SQL.
Date Users previous_year
2022-01-01 10 5
2022-01-02 20 15
The code is written as follows.
select CAST(root_tstamp as DATE) as Date,
count(DISTINCT userid) as users,
count(Distinct case when CAST(root_tstamp as DATE) = dateadd(MONTH,-12,CAST(root_tstamp as DATE)) then userid end) as previous_year
FROM table1
But it returns 0 for previous_year values.
How can I fix that?
Possible solution for SQL Server:
WITH cte AS ( SELECT 2022 [year]
UNION ALL
SELECT 2021 )
SELECT cte.[year],
COUNT(DISTINCT test.userId) current_users_amount,
COUNT(DISTINCT CASE WHEN YEAR(test.root_tstamp) < cte.[year]
THEN test.userId
END) previous_users_amount
FROM test
JOIN cte ON YEAR(test.root_tstamp) <= cte.[year]
GROUP BY cte.[year]
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=88b78aad9acd965bdbac4c85a0b81927
This query (for MySql) returns unique number of userids where the root_timestamp is in the current year, by day, and the number of unique userids for the same day last year. If there is no record for a day in the current year nothing will be displayed for that day. If there are rows for the current year, but no rows for the same day last year, then NULL will be shown for that lastyear column.
SELECT cast(ty.root_tstamp as date) as Dte,
COUNT(DISTINCT ty.userId) as users_this_day,
count(distinct lysd.userid) as users_sameday_lastyear
FROM test ty
left join
test lysd
on cast(lysd.root_tstamp as date)=date_add(cast(ty.root_tstamp as date), interval -1 year)
WHERE YEAR(ty.root_tstamp) = year(current_date())
GROUP BY Dte
If you wish to show output rows for calendar days even if there are no rows in current year and/or last year, then you also need a calendar table to be introduced (let's hope that it is not what you need)

Generate new table base on date sub?

I have a tables like this.
Name
Created
Frank
20210321
Jack
20210324
And expect output table:
Name
TaskID
Frank
Frank-20210321
Frank
Frank-20210322
Frank
Frank-20210323
Frank
Frank-20210324
Jack
Frank-20210324
Assume today is 20210324, and How to generate a new table?
What i have tried.
SELECT name, concat(name, "-", created)
And I know I can use
SELECT DATEDIFF('2021-03-25', '2021-03-21') as DAYS;
To calculate a different days.
But it just simple one task was generate per each line.
WITH RECURSIVE
cte AS ( SELECT CAST(MIN(Created) AS DATE) d FROM test
UNION ALL
SELECT d + INTERVAL 1 DAY FROM cte WHERE d < CURRENT_DATE )
SELECT test.name, CONCAT(test.name, '-', DATE_FORMAT(cte.d, '%Y%m%d')) TaskID
FROM cte
JOIN test ON cte.d >= test.Created
ORDER BY TaskID
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=1e086f9ce8ed6b32713f2932549f295c

need to fetch all the students who have not paid for the current month

I have two tables
Students table :
id studentname admissionno
3 test3 3
2 test2 2
1 test 1
2nd table is fee :
id studentid created
1 3 2015-06-06 22:55:34
2 2 2015-05-07 13:32:48
3 1 2015-06-07 17:47:46
I need to fetch the students who haven't paid for the current month,
I'm performing the following query:
SELECT studentname FROM students
WHERE studentname != (select students.studentname from students
JOIN submit_fee
ON (students.id=submit_fee.studentid)
WHERE MONTH(CURDATE()) = MONTH(submit_fee.created)) ;
and I'm getting error:
'#1242 - Subquery returns more than 1 row'
Can you tell me what the correct query is to fetch all the students who haven't paid for the current month?
Use not in, please try query below :
SELECT s.*
FROM students s
WHERE s.id NOT IN ( SELECT sf.studentid FROM studentfees sf WHERE month(sf.created) = EXTRACT(month FROM (NOW())) )
You want to use not exists or a left join for this:
select s.*
from students s
where not exists (select 1
from studentfees sf
where s.id = sf.studentid and
sf.created >= date_sub(curdate(), interval day(curdate) - 1) and
sf.created < date_add(date_sub(curdate(), interval day(curdate) - 1), 1 month)
)
Note the careful construction of the date arithmetic. All the functions are on curdate() rather than on created. This allows MySQL to use an index for the where clause, if one is appropriate. One error in your query is the use of MONTH() without using YEAR(). In general, the two would normally be used together, unless you really want to combine months from different years.
Also, note that paying or not paying for the current month may not really answer the question. What if a student paid for the current month but missed the previous month's payment?

Cumulative SQL to work out no of payers

Currently trying to create a query that shows how many accounts have paid month on month but on a cumulative basis (penetration). So as an example I have a table with Month paid and account number, which shows what month that account paid.
Month | AccountNo
Jan-14 | 123456
Feb-14 | 321654
So using the above the result set would show
Month | Payers
Jan-14 | 1
Feb-14 | 2
being because one account paid in Jan, then one in Feb meaning that there have been by the end of Feb 2 payments overall, but only one in Jan. Tried a few inner joins back onto the table itself with a t1.Month >= t2.Month as i would for a normal cumulative query but the result is always out.
Any questions please ask, unsure if the above will be clear to anyone but me.
If you have date in the table then you can try the following query.
SELECT [Month]
,(SELECT COUNT(AccountNo)
FROM theTable i
-- This is to make sure to add until the last day of the current month.
WHERE i.[Date] <= DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,o.[Date])+1,0)) AS CumulativeCount
FROM theTable o
Ok, several things. You need to have an actual date field, as you can't order by the month column you have.
You need to consider there may be gaps in the months - i.e. some months where there is no payment (not sure if that is true or not)
I'd recommend a recursive common table expression to do the actual aggregation
Heres how it works out:
-- setup
DECLARE #t TABLE ([Month] NCHAR(6), AccountNo INT)
INSERT #t ( [Month], AccountNo )
VALUES ( 'Jan-14',123456),('Feb-14',456789),('Apr-14',567890)
-- assume no payments in march
; WITH
t2 AS -- get a date column we can sort on
(
SELECT [Month],
CONVERT(DATETIME, '01 ' + REPLACE([Month], '-',' '), 6) AS MonthStart,
AccountNo
FROM #t
),
t3 AS -- group by to get the number of payments in each month
(
SELECT [Month], MonthStart, COUNT(1) AS PaymentCount FROM t2
GROUP BY t2.[Month], t2.MonthStart
),
t4 AS -- get a row number column to order by (accounting for gaps)
(
SELECT [Month], MonthStart, PaymentCount,
ROW_NUMBER() OVER (ORDER BY MonthStart) AS rn FROM t3
),
t5 AS -- recursive common table expression to aggregate subsequent rows
(
SELECT [Month], MonthStart, PaymentCount AS CumulativePaymentCount, rn
FROM t4 WHERE rn = 1
UNION ALL
SELECT t4.[Month], t4.MonthStart,
t4.PaymentCount + t5.CumulativePaymentCount AS CumulativePaymentCount, t4.rn
FROM t5 JOIN t4 ON t5.rn + 1 = t4.rn
)
SELECT [Month], CumulativePaymentCount FROM t5 -- select desired results
and the results...
Month CumulativePaymentCount
Jan-14 1
Feb-14 2
Apr-14 3
If your month column is date type then its easy to work on else you need some additional conversion for it. Here the query goes...
create table example (
MONTHS datetime,
AccountNo INT
)
GO
insert into example values ('01/Jan/2009',300345)
insert into example values ('01/Feb/2009',300346)
insert into example values ('01/Feb/2009',300347)
insert into example values ('01/Mar/2009',300348)
insert into example values ('01/Feb/2009',300349)
insert into example values ('01/Mar/2009',300350)
SELECT distinct datepart (m,months),
(SELECT count(accountno)
FROM example b
WHERE datepart (m,b.MONTHS) <= datepart (m,a.MONTHS)) AS Total FROM example a

sql query to get duplicate records with different dates

I need to get records with different date field ,
table Sites:
field id
reference
created
Every day we add lot of records, so I need to do a function that extract all records existing with duplicates of rows just was added, to do some notifications.
the conditions that i can't get is the difference between records of the current day and the old data in the table should be (one day to 4 days) .
If is there any simple query to do that without using transaction .
I'm not sure I totally understand what you mean by duplicate records, but here's a basic date query:
SELECT fieldId, reference, created, DATE(created) as the_date
FROM Sites
WHERE the_date
BETWEEN DATE( DATE_SUB( NOW() , INTERVAL 3 DAY ) )
AND DATE ( NOW() )
I'm making several assumptions such as:
You don't want the "first" row returned
Duplicates don't carry the
date forward (The next after initial 4 days is not a duplicate)
The 4 days means +4 days so Day 5 is included
So, my code is :
with originals as (
select s1.*
from sites as s1
where 0 = (
select count(*)
from sites as s2
where s1.field_id = s2.field_id
and s1.reference = s2.reference
and s1.created <> s2.created
and DATEDIFF(DAY,s2.created, s1.created) between 1 and 4
)
)
select s1.*
from sites as s1
inner join originals as o
on s1.field_id = o.field_id
and s1.reference = o.reference
and s1.created <> o.created
where DATEDIFF(DAY,o.created, s1.created) between 1 and 4
order by 1,2,3;
Here it is in a fiddle: http://sqlfiddle.com/#!3/9b407/20
This could be simpler if some conditions are relaxed.
thanks a lot for every one who tried to help me ,
i have found this solution after lot of test
SELECT `id`,`reference`,count(`config_id`) as c,`created` FROM `sites`
where datediff(date(current_date()),date(`created`)) < 4
group by `reference`
having c > 1
thanks a lot for your help