I have a query that shows all workers with their first shift in the last week, it's gathered from two tables and looks like this:
SELECT MIN(p.start_date),
CONCAT(c.first_name, ' ', c.last_name) AS 'c.fullname',
c.temp_nr
FROM contactstable c
LEFT JOIN projectlines p on c.temp_nr = p.candidate_number
WHERE c.contact_type = 'Candidate'
GROUP BY c.temp_nr
HAVING
MIN(p.start_date)
between
DATE_SUB(CURDATE(), INTERVAL (dayofweek(CURDATE())+6) DAY)
AND DATE_SUB(CURDATE() , INTERVAL (dayofweek(CURDATE())) DAY)
My problem is the query times out, so as I understand it I need to add indexes, but after having searched around on multiple sites, I still have no clue how to go about that.
I am using Workbench 8.0
I would suggest that you write the query like this:
SELECT CONCAT(c.first_name, ' ', c.last_name) AS fullname, c.temp_nr,
(SELECT MIN(p.start_date)
FROM projectlines p
WHERE c.temp_nr = p.candidate_number
) as min_start_date
FROM contactstable c
WHERE c.contact_type = 'Candidate'
HAVING min_start_date BETWEEN DATE_SUB(CURDATE(), INTERVAL (dayofweek(CURDATE())+6) DAY) AND
DATE_SUB(CURDATE() , INTERVAL (dayofweek(CURDATE())) DAY);
Then for this, you want indexes on:
contactstable(contact_type, temp_nr, first_name, last_name)
projectlines(candidate_number, start_date).
Related
please help me, I want to display data with eloquent, before that I have to create a Raw Query to make it easier for me when I want to implement it to Eloquent.
I want to get a result like this :
What I want
I've tried using this query, but the result is not what I want.
SELECT COUNT(t.pengaduan_id) jml, t.kanal_id, mpk.nama_kanal, DATE_FORMAT(t.created_at, '%M %Y') tgl
FROM tr_pengaduan AS t
LEFT JOIN ms_pengaduan_kanal mpk ON t.kanal_id = mpk.kanal_id
GROUP BY YEAR(t.created_at),MONTH(t.created_at) ORDER BY kanal_id
Result of the above query :
Result
Here are the details from the table :
1. Table Tr_pengaduan : Tr_pengaduan
2. Table ms_pengaduan_kanal : ms_pengaduan_kanal
Is there a way to get the result I want with/without creating a procedure or function? I really appreciate it if you reply with Raw Query or Eloquent or both.
UPDATE :
I tried #ProGu 's suggestion, but the result of the join is partially NULL.
SELECT COUNT(t.pengaduan_id) jml, t.kanal_id, mpk.nama_kanal, DATE_FORMAT(t.created_at, '%M %Y') tgl, mont.MONTH
FROM tr_pengaduan AS t
LEFT JOIN ms_pengaduan_kanal mpk ON t.kanal_id = mpk.kanal_id
LEFT JOIN (SELECT MONTH(CURRENT_DATE()) AS
MONTH
UNION SELECT MONTH(CURRENT_DATE())-1 AS
MONTH
UNION SELECT MONTH(CURRENT_DATE())-2 AS
MONTH
UNION SELECT MONTH(CURRENT_DATE())-3 AS
MONTH
UNION SELECT MONTH(CURRENT_DATE())-4 AS
MONTH) AS mont ON MONTH(t.created_at) = mont.MONTH
WHERE t.kanal_id = mpk.kanal_id
GROUP BY mpk.kanal_id ORDER BY kanal_id
Result : Update Result
try something like this:
three parts in the query
month5 - represent current month and previous 4 months
t - id and names for result set
counts - counting results for last 5 months
SELECT COALESCE(counts.jml, 0) counts, t.kanal_id, t.nama_kanal, DATE_FORMAT(CURDATE() - INTERVAL month5.months MONTH, '%M %Y') tgl
FROM (
SELECT 0 AS months
UNION
SELECT 1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
) month5
CROSS JOIN (
SELECT t.kanal_id, MAX(mpk.nama_kanal) nama_kanal
FROM tr_pengaduan t
LEFT JOIN ms_pengaduan_kanal mpk ON t.kanal_id = mpk.kanal_id
WHERE t.created_at BETWEEN CURDATE() - INTERVAL DAY(CURDATE()) - 1 DAY - INTERVAL 4 MONTH AND NOW()
GROUP BY t.kanal_id
) t
LEFT JOIN (
SELECT COUNT(t.pengaduan_id) jml, t.kanal_id, DATE(MAX(t.created_at)) tgl
FROM tr_pengaduan AS t
WHERE t.created_at BETWEEN CURDATE() - INTERVAL DAY(CURDATE()) - 1 DAY - INTERVAL 4 MONTH AND NOW()
GROUP BY t.kanal_id, YEAR(t.created_at), MONTH(t.created_at)
) counts ON LAST_DAY(counts.tgl) = LAST_DAY(CURDATE() - INTERVAL month5.months MONTH) AND t.kanal_id = counts.kanal_id
ORDER BY kanal_id, tgl
I am trying to extract a list of workers who had their first shift during last week.
Right now, my SQL works if I put a specific worker with a first shift in last week in my where clause (WHERE c.temp_nr ='XXXX'), but when I remove that clause, it just timeout
SELECT MIN(p.start_date), CONCAT(c.first_name, ' ', c.last_name) AS 'c.fullname', c.temp_nr
FROM contactstable c
LEFT JOIN projectlines p on c.temp_nr = p.candidate_number
WHERE c.temp_nr ='XXXX' and c.contact_type = 'Candidate'
HAVING MIN(p.start_date) between DATE_SUB( CURDATE( ) , INTERVAL (dayofweek(CURDATE())+6)
DAY )
AND DATE_SUB( CURDATE( ) , INTERVAL (dayofweek(CURDATE()))
DAY )
Use GROUP BY c.temp_nr
SELECT MIN(p.start_date), CONCAT(c.first_name, ' ', c.last_name) AS 'c.fullname', c.temp_nr
FROM contactstable c
LEFT JOIN projectlines p on c.temp_nr = p.candidate_number
WHERE c.contact_type = 'Candidate'
GROUP BY c.temp_nr
HAVING
MIN(p.start_date)
between
DATE_SUB(CURDATE(), INTERVAL (dayofweek(CURDATE())+6) DAY)
AND DATE_SUB(CURDATE() , INTERVAL (dayofweek(CURDATE())) DAY)
I am trying to concat count of id and 1 inside group_concat. Below is my query.
MYSQL:
SELECT
months.name AS NAME,
CONCAT(
'[',
GROUP_CONCAT(
CONCAT(
'[\"',
COUNT(p_c_n_details.JPN_ID),
'\",',
1,
']'
)
),
']'
) AS DATA
FROM
p_c_n_details
INNER JOIN in_e_s_s__p_c_ns RIGHT OUTER JOIN months ON months.id =
MONTH(p_c_n_details.created_at) AND p_c_n_details.type IN('Process Change',
'Design Change') AND p_c_n_details.JPN_ID =
in_e_s_s__p_c_ns.juniperinternalpcnid AND p_c_n_details.created_at >=
last_day(NOW()) + INTERVAL 1 DAY - INTERVAL 3 MONTH
WHERE
months.name IN(
MONTHNAME(
DATE_SUB(CURDATE(), INTERVAL 0 MONTH)),
MONTHNAME(
DATE_SUB(CURDATE(), INTERVAL 1 MONTH)),
MONTHNAME(
DATE_SUB(CURDATE(), INTERVAL 2 MONTH))
)
GROUP BY
months.id
Expected Output:
Name | DATA
-------------------------
July [20,1]
August [33,1]
Table months contains month names.
But I am getting error #1111 - Invalid use of group function. I tried this link
mysql group_concat with a count inside?
but I am facing error when using in my query.
This is a guess.
Try:
SELECT months.name AS NAME,
CONCAT('{',COUNT(p_c_n_details.JPN_ID),',1}' AS DATA
in place of the SELECT you now have.
Your example result doesn't show a need for GROUP_CONCAT().
I read many topics to fetch data that posted in different periods, but as the Time in my mysql table is in STRING format I couldn't make it happen.
SELECT s.user_id, count(*) AS wins, u.username, u.avatar,u.avatar_uploaded
FROM on_scores AS s
LEFT JOIN on_users AS u ON (u.userid = s.user_id)
WHERE s.is_high = '1' AND DATE(s.date_score) >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP BY s.user_id
ORDER BY wins DESC
LIMIT 10
I tried the STR_TO_DATE method but still no output.
Use the from_unixtime function to get the time into a date-like format.
More info here.
Information on formatting the resultant date - here.
Example:
select date_sub( from_unixtime( s.datescore ), INTERVAL 1 MONTH ) as monthfromdatevalue;
select datediff( from_unixtime( s.datescore, curdate()) as howlongago_fromtoday;
I'm trying to run a mysql select statement where it looks at today's date and only returns results that signed up on that current day. I've currently tried the following, but it doesn't seem to work.
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE users.signup_date = CURDATE()
I've modified my SELECT statement to this, thanks guys.
SELECT id FROM users WHERE DATE(signup_date) = CURDATE()
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE DATE(signup_date) = CURDATE()
This query will use index if you have it for signup_date field
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE signup_date >= CURDATE() && signup_date < (CURDATE() + INTERVAL 1 DAY)
Sounds like you need to add the formatting to the WHERE:
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE DATE_FORMAT(users.signup_date, '%Y-%m-%d') = CURDATE()
See SQL Fiddle with Demo
You can use the CONCAT with CURDATE() to the entire time of the day and then filter by using the BETWEEN in WHERE condition:
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE (users.signup_date BETWEEN CONCAT(CURDATE(), ' 00:00:00') AND CONCAT(CURDATE(), ' 23:59:59'))
This is a simple code to find date
SELECT users.id, DATE_FORMAT(users.signup_date, '%Y-%m-%d')
FROM users
WHERE DATE_FORMAT(users.signup_date, '%Y-%m-%d') = CURDATE()