SQL: using group by concat() - mysql

I have a query which returns result of number of calls made by customers and some suggestions made for customers and etc.. for that particular date ie... grouping it by date
But now I want to find number of customers I tried grouping by lead_id and cuncat(lead_id,timecreatredFormat) still there is a data mismatch
Below is the query that I have tried
select
sum(t.enquiry_cnt),
sum(t.suggested_cnt),
sum(t.tot_cnt)
from
(select
case
when source = 1 then 1
else 0
end enquiry_cnt,
case
when source = 6 then 1
else 0
end suggested_cnt,
case
when (source = 1 || source = 6) then 1
else 0
end tot_cnt,
date_format(timecreated, '%d-%b-%Y') created_time,
lead_id,timecreated
from
mg_lead_suggested_listing group by concat(created_time,lead_id) ) t
group by t.created_time
order by t.timecreated desc
limit 10;
Thanks in advance

Check whether following query is correct or not. I have added COUNT(DISTINCT t.lead_id) to get customer count.
DECLARE #TEMP TABLE
(
[source] INT,
lead_id INT,
timecreated DATETIME
)
INSERT INTO #TEMP VALUES (1,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (1,2,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
SELECT
CAST(t.timecreated AS DATE) [date],
SUM(t.enquiry_cnt) enquiry_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 1) as lead_enquiry_cnt,
SUM(t.suggested_cnt) suggested_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 6) as lead_suggested_cnt,
SUM(t.tot_cnt) tot_cnt,
COUNT(t.lead_id) as lead_cnt
FROM
(
SELECT
CASE
WHEN [source] = 1 THEN 1
ELSE 0
END enquiry_cnt,
CASE
WHEN [source] = 6 THEN 1
ELSE 0
END suggested_cnt,
CASE
WHEN ([source] = 1 OR [source] = 6) THEN 1
ELSE 0
END tot_cnt,
lead_id,
timecreated
FROM
#TEMP
) AS t
group by
CAST(t.timecreated AS DATE)
order by
[date] desc

Related

sql update max(date) group by

raw data
no
group
date
value
flag
1
a
2022-10-13
old
y
2
a
2022-10-15
new
y
3
b
2022-01-01
old
n
4
b
2022-01-03
new
n
step1. insert no1 raw
step2. modify date value using by no2 raw
and I want to update latest date no1 raw using by no2 raw
and the condition is where `flag` = "y"
final sql table
no
group
date
value
flag
1
a
2022-10-15
old
y
3
b
2022-01-01
old
n
is it possible?
+) I insert/update raw data line by line.
Not entirely clear but I hope below answer gives you a hint if not the solution.
select no,
`group`,
case when flag='Y' then mx_dt else `date` end as new_date,
value,
flag
from ( select no,
`group`,
value,
`date`,
flag ,
row_number() over(partition by `group` order by `date` asc ) as rn,
max(`date`) over (partition by `group`,(case when flag <> 'Y' then `date` end) ) mx_dt
from raw_data
) as tbl
where rn=1;
Above code will select the max(date) per group if the flag=Y otherwise it will take the date per row.
https://dbfiddle.uk/JhRUti2h
The solution is to self join the source table and select the right field, prioritizing the latest date.
Here you have a working query:
WITH source_data AS (
SELECT 1 AS no_, 'a' AS group_, CAST('2022-10-13' AS DATE) AS date, 'old' AS value, 'y' AS flag
UNION ALL
SELECT 2, 'a', CAST('2022-10-15' AS DATE), 'new', 'y'
UNION ALL
SELECT 3, 'b', CAST('2022-01-01' AS DATE), 'old', 'n'
UNION ALL
SELECT 4, 'b', CAST('2022-01-03' AS DATE), 'new', 'n')
SELECT no_, group_, COALESCE(new_date, date), value, flag
FROM
(SELECT * FROM source_data WHERE value = 'old') old_values
LEFT JOIN (SELECT group_ AS new_group, date AS new_date FROM source_data WHERE value = 'new' AND flag='y') new_values
ON old_values.group_ = new_values.new_group
The result is what you expected:
no_ group_ f0_ value flag
1 a 2022-10-15 old y
3 b 2022-01-01 old n

MySQL Attendance Calculation

Here i have table attendances
I need result as shown below
How can i achieve this in mysql without using any programming language
Sql File is Attendances.sql
We can try a pivot query approach, aggregating by user and date:
SELECT
user_id,
DATE(date_time) AS date,
TIMESTAMPDIFF(MINUTE,
MAX(CASE WHEN status = 'IN' THEN date_time END),
MAX(CASE WHEN status = 'OUT' THEN date_time END)) / 60.0 AS hours
FROM yourTable
GROUP BY
user_id,
DATE(date_time);
The caveats of this answer are many. It assumes that there would be only one IN and OUT entry, per user, per day. If a period could cross over dates, then my answer might not generate correct results. Also, if an IN or OUT value be missing, then NULL would be reported for the hours value.
I have Achieve it my self by creating a mysql function and view
Mysql View
CREATE OR REPLACE VIEW `view_attendances` AS
SELECT
`a`.`id` AS `a1_id`,
`a`.`user_id` AS `user_id`,
CAST(`a`.`date_time` AS DATE) AS `date`,
`a`.`date_time` AS `in`,
`a2`.`id` AS `a2_id`,
`a2`.`date_time` AS `out`,
(TIMESTAMPDIFF(SECOND,
`a`.`date_time`,
`a2`.`date_time`) / 3600) AS `hours`
FROM
(`attendances` `a`
JOIN `attendances` `a2` ON (((`a`.`is_confirm` = 1)
AND (`a`.`status` = 'IN')
AND (`a2`.`id` = FN_NEXT_OUT_ATTENDANCE_ID(`a`.`user_id`, `a`.`date_time`, `a`.`status`))
AND (a2.status = 'OUT')
AND (CAST(`a`.`date_time` AS DATE) = CAST(`a2`.`date_time` AS DATE)))))
Mysql Function
CREATE FUNCTION `fn_next_out_attendance_id`( _user_id INT, _attendance_date_time DATETIME, _status VARCHAR(10) ) RETURNS int(11)
BEGIN
DECLARE _id INT(11);
SELECT
id INTO _id
FROM
attendances
WHERE
is_confirm = 1
AND user_id = _user_id
AND date_time > _attendance_date_time
AND `status` <> _status
ORDER BY
date_time ASC LIMIT 1 ;
RETURN if (_id IS NULL, 0, _id);
END

Return Value from sql commands

I am currently using the SQL command
Select * from where name='john'
Is it possible to return 20 no matter the query, for example
Select * from where name='john' or return = 20
EDIT
If you have an oracle database you can do something like that:
SELECT *
FROM dual
WHERE 1=0
UNION
SELECT '20'
FROM dual;
check my answer
if exists (Select * from item where ItemName='ABC Daycare1')
begin
Select * from item where ItemName='ABC Daycare1'
end
else
select '20'
Try running this. This should return the top result (which is never 20 due to the custom sort) and then when the name doesn't match a value it returns 'Mark' and 20
SQL
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #temp (id int NOT NULL, name varchar(255) NOT NULL)
INSERT INTO #temp (id, name) VALUES (88,'John')
INSERT INTO #temp (id, name) VALUES (20,'Mark')
SELECT TOP 1
*
FROM #temp
WHERE (name = 'Mark' OR name = 'John')
ORDER BY (
CASE
WHEN id = 20 THEN 0 ELSE 1
END) DESC
MySQL - MySQL fiddle
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #temp (id int NOT NULL, name varchar(255) NOT NULL)
INSERT INTO #temp (id, name) VALUES (88,'John')
INSERT INTO #temp (id, name) VALUES (20,'Mark')
SELECT
*
FROM temp
WHERE (name = 'Mark' OR name = 'John')
ORDER BY (
CASE
WHEN id = 20 THEN 0 ELSE 1
END) DESC
LIMIT 1

How to search sequence of Date Ranges in SQL

When trying to check date ranges it does not return values. Here st_date and end_date for usr_id = 1 is sequence so it should return only usr_id = 1 values and should not return usr_id = 3 since it is not sequence . If the date range is not in sequence, it should not return any value.
CREATE TABLE #temp(st_date DATE,end_date DATE,usr_id INT)
INSERT #temp
VALUES ('2007-03-01 ','2015-01-31 ',1),
('2015-02-01 ','2017-04-01 ',1),
('2007-03-01 ','2014-01-31 ',2),
('2007-03-01 ','2015-01-31 ',3),
('2015-03-02 ','2017-04-01 ',3)
DECLARE #st_dt DATE = '2009-02-01 00:00:00',#end_dt DATE = '2017-01-01 00:00:00'
SELECT * FROM #temp WHERE #st_dt BETWEEN st_date AND end_date
AND #end_dt BETWEEN st_date AND end_date
DROP TABLE #temp
SELECT *
FROM #temp t
INNER JOIN #temp t2 ON t.usr_id = t2.usr_id AND t.end_date = DATEADD(dd, -1, t2.st_date)
WHERE #st_dt BETWEEN t.st_date AND t.end_date
AND #end_dt BETWEEN t2.st_date AND t2.end_date

Getting count of total present and absent in single sql query

Here is my attendance table details Emp_ID(varchar),pdate(datetime),attendance(char(2))
i want to get the total count of attendence days ,total count of absent and total count of present in a single query for a particular date range grouping by emp_id
just an sample example to show you how to proceed with your data
declare #t table (id int,da date,attend Varchar(2))
insert into #t (id,da,attend) values (1,'20141011','P'),
(1,'20141012','A'),
(1,'20141013','P'),
(1,'20141014','A'),
(1,'20141014','P')
select ID,COUNT(da)Total,
(select COUNT(da) from #t where attend = 'A')as Absent,
(select COUNT(da) from #t where attend = 'P')as Present from #t
group by id
this worked for me.
select Emp_ID
,count(case when status ='A' then 1 end) as absent_count
,count(case when status ='P' then 1 end) as present_count
,count(distinct pdate) as Tot_count
from MASTERPROCESSDAILYDATA where pdate between '2014-01-01' and '2014-01-31'
group
by Emp_ID ;
You should try something like that
SELECT Emp_id, present, absent FROM details
NATURAL JOIN(
SELECT COUNT(*) AS present FROM details WHERE Emp_id = table.Emp_id AND attendence='P'
JOIN
SELECT COUNT(*) AS absent FROM details WHERE Emp_id = table.Emp_id AND attendence='A' ) AS ctt
You could use group by, as already demonstrated.
Or you can use window functions/analytic functions.
DECLARE #T TABLE (Emp_id INT,pdate DATE,attendance VARCHAR(2))
INSERT INTO #t (emp_id,pdate,attendance) VALUES (1,'20141011','P'),
(1,'20141012','A'),
(1,'20141013','P'),
(1,'20141014','A'),
(1,'20141014','P')
SELECT
DISTINCT
EMP_ID,
Attendance,
COUNT(*) OVER (PARTITION BY attendance) as CntAttendance
FROM
#t
Try the script below;
select id,
count(distinct pdate) as Total_Attendance_Days,
sum(case when attendance= 'p' then 1 else 0 end) Presents,
sum(case when att = 'a' then 1 else 0 end) Absents
from ##TT
where pdate between '01/04/2015' and '15/04/2015'
group by id
Hope this helps