Maybe someone could really help me here. I need some guidance. How come when I try to do a SUM in a column from a JOIN table the SUM form the main table returns wrong results? Let's say if sum from table A is 6 but there are 3 records that join with table B then the results turns from 6 to 18.. I just can't seem to get it. Thank you
SELECT SUM(tm_hours) AS total_hours,
SUM(drive_time) AS drive_time,
STR_TO_DATE(CONCAT(YEAR(tm_date),WEEK(tm_date),' Monday'), '%X%V %W') AS weeks
FROM `bhds_timecard`
LEFT JOIN bhds_mileage
ON bhds_timecard.case_no = bhds_mileage.case_no
WHERE bhds_timecard.ds_id = '3' AND tm_date BETWEEN '2016-03-16' AND '2016-03-31'
GROUP BY CONCAT(YEAR(tm_date), WEEK(tm_date))
Output should look something like that I modified the query but I am still getting wrong drive time. drive time for the firs week should be 55 that is because it is only taking the drive time from one day
Try the following:
SELECT SUM(hours) as total_hours, SUM(drive_time), weeks
FROM ( SELECT tm_hours AS hours,
SUM(drive_time) AS drive_time,
STR_TO_DATE(CONCAT(YEAR(tm_date),
WEEK(tm_date),' Monday'), '%X%V %W') AS weeks,
bhds_timecard.case_no
FROM `bhds_timecard`
LEFT JOIN bhds_mileage
ON bhds_timecard.case_no = bhds_mileage.case_no
WHERE bhds_timecard.ds_id = '3'
AND tm_date BETWEEN '2016-03-16' AND '2016-03-31'
GROUP BY weeks, bhds_timecard.case_no
) as innersums
GROUP by weeks;
Related
I have two tables:
table 1.a
id--entry_date-amount
============================
2---2016-04-14--$400
3---2016-04-14--$400
4----2017-07-14--$200
5---2017-07-14--$500
6---2017-05-14--$600
7----2017-06-18--$100
table 2.b
id--entry_date
===========================
2---2016-04-14--$230
3---2016-04-14--$230
4----2017-07-14--$567
5---2017-07-14--$600
6---2017-05-14--$560
7----2017-06-18--$90
8---2016-04-14--$100
from the two tables how can i get count with montwise
my desired result:
month_name--total(count form table a)--total(count form table b)--amount(table a)--amount(table b)
========================================================
April,16-----------2-------------------3---$800-$500
May,17-----------1-------------------1 --$600--$700
June,17-----------2-------------------2--$100--$800
July,17-----------2-------------------2---$700-$400
this is the demo data.
I want to show data from two tables in a single query month wise.
How can i do this?
I tried:
SELECT MONTHNAME(r.entry_date),r.a_total FROM(
SELECT
IFNULL((SELECT COUNT(tr.id) AS amount FROM a AS tr WHERE MONTH(tr.entry_date)=MONTH(t.entry_date)),0) AS a_total
,t.entry_date
FROM(SELECT tr.id,tr.entry_date
FROM a AS tr
WHERE DATE(tr.entry_date) BETWEEN '2017-07-01' AND '2018-06-30') t
GROUP BY MONTH(t.entry_date)) r
But takes 58 seconds for simple query. How can i make this in a simple query?
You can get the counts and sum from each table individually, then use UNION to combine the two result sets into one result set. Something like this :
SELECT Month_name,
SUM(aCount) AS aCount,
SUM(bCount) AS bCount,
SUM(aAmount) AS aAmount,
SUM(bAmount) AS bAmount
FROM
(
SELECT
MONTHNAME(a.entry_date) AS Month_name,
COUNT(a.id) AS aCount,
0 AS bCount,
SUM(a.amount) AS aAmount,
0 AS bAmount
FROM a
GROUP BY MONTHNAME(a.entry_date)
UNION ALL
SELECT
MONTHNAME(b.entry_date) AS Month_name,
0 AS aCount,
COUNT(b.id) AS bCount,
0 AS aAmount,
SUM(b.amount) AS bAmount
FROM b
GROUP BY MONTHNAME(b.entry_date)
) AS t
GROUP BY Month_Name;
live demo
user9131497 has a good design for the big picture. However, I would suggest stuff like this for handling the dates:
SELECT DATE_FORMAT(entry_date, "%M,%y") AS 'Month',
COUNT(*) AS 'aCount'
FROM a
GROUP BY LEFT(entry_date, 7) -- eg, "2017-03"
Try that to see what I mean.
Note that this will work beyond a year. Or did you need January values from all years to be combined?? -- That's what your solution and user9131497's will do. Mine keeps them separate.
I have a table of hours which looks like :
I want to sum the hours_spent results for this week only and group the results by the created_by person. I have this query which returns the correct data for showing only results in this week :
SELECT staff_id, first_name, last_name, date_entered, `hours_spent` as total_hours FROM hours LEFT JOIN staff ON hours.created_by = staff.staff_id where yearweek(`date_entered`) = yearweek(curdate());
But when I add the SUM(hours_spent) as total_hours and group by staff_id like the example below I get 0 results.
SELECT staff_id, date_entered, first_name, last_name, SUM(`hours_spent`) as total_hours FROM hours LEFT JOIN staff ON hours.created_by = staff.staff_id group by staff_id having yearweek(`date_entered`) = yearweek(curdate());
I'm assuming it's not working because the Having part of my statement doesn't return individual rows of dates so it breaks.
I feel like I am doing this the hard way. Should I be trying to run a second summing query on the results of the first query rather than combine it all into one (I was hoping for cleanliness). Or should I be using a subquery to filter out the dates that aren't this week then group the totals if so how could I accomplish this?
I got what I was expecting with :
SELECT staff.first_name,staff.last_name, sum(hours_spent)
FROM hours
LEFT JOIN staff ON hours.created_by = staff.staff_id
WHERE yearweek(date_entered,1) = (yearweek(curdate(),1)-1)
GROUP BY created_by
I am trying to calculate the difference of values list coming from a database.
I would like to achieve it using php or mysql, but I do not know how to proceed.
I have a table named player_scores. One of its rows contains the goals scored.
Ex.
pl_date pl_scores
03/11/2014 18
02/11/2014 15
01/11/2014 10
I would like to echo the difference between the goals scored during the matches played in different dates.
Ex:
pl_date pl_scores diff
03/11/2014 18 +3
02/11/2014 15 +5
01/11/2014 10 no diff
How can I obtain the desired result?
You seem to want to compare a score against the score on a previous row.
Possibly simplest if done using a a sub query that gets the max pl_date that is less than the pl_date for the current row, then joining the results of that sub query back against the player_scores table to get the details for each date:-
SELECT ps1.pl_date, ps1.pl_scores, IF(ps2.pl_date IS NULL OR ps1.pl_scores = ps1.pl_scores, 'no diff', ps1.pl_scores - ps1.pl_scores) AS diff
FROM
(
SELECT ps1.pl_date, MAX(ps2.pl_date) prev_date
FROM player_scores ps1
LEFT OUTER JOIN player_scores ps2
ON ps1.pl_date > ps2.pl_date
GROUP BY ps1.pl_date
) sub0
INNER JOIN player_scores ps1
ON sub0.pl_date = ps1.pl_date
LEFT OUTER JOIN player_scores ps2
ON sub0.prev_date = ps2.pl_date
There are potentially other ways to do this (for example, using variables to work through the results of an ordered sub query, comparing each row with the value stored in the variable for the previous row)
SELECT score FROM TABLE WHERE DATE = TheDateYouWant
$score = $data['score'];
SELECT score FROM TABLE WHERE date = dateYouWant
$difference = $score - $data['score'];
Something like this?
You could use two queries, one to get the value to use in the comparison (in the example below is the smaller number of scores) and the second one to get the records with a dedicated column with the difference:
SELECT MIN(pl_scores);
SELECT pl_date, pl_scores, (pl_scores - minScore) as diff FROM player_scores;
Or, using a transaction (one query execution php side):
START TRANSACTION;
SELECT MIN(Importo) FROM Transazione INTO #min;
SELECT Importo, (Importo - #min) as diff FROM Transazione;
select *,
coalesce(
(SELECT concat(IF(t1.pl_scores>t2.pl_scores,'+',''),(t1.pl_scores-t2.pl_scores))
FROM tableX t2 WHERE t2.pl_date<t1.pl_date ORDER BY t2.pl_date DESC LIMIT 1)
, 'no data' ) as diff
FROM tableX t1
WHERE 1
order by t1.pl_date DESC
I've got two tables in MySql
1 (Staff): Id/Name/SecondName
2 (fee):
Id/StaffId/Date(yyyy-mm-dd)/HoursWorked(hh:mm)/fee(int)/workType
There is also a script adding records to fee table.
I'm trying to group data in php to create html table like:
Name, Second Name | January 2009 | 123:45 hours | 2100,00 USD
February 2009...
March 2009 ....
Next person... etc.
So generally I'm trying to sum fee and hours in specific month and print a report from database...
And I need some advice/help... What is the bast way to create table like this?
Maybe something like this? Not tested though...
SELECT s.Name, s.SecondName, CONCAT(DAYOFMONTH(f.Date),', ',YEAR(f.Date)),
SUM (f.HoursWorked), SUM(f.Fee)
FROM Staff s
JOIN Fee f ON f.StaffId = s.Id
GROUP BY s.Id, YEAR(f.Date), MONTH(f.Date)
Edit: Ofcourse you need to group on s.Id...
That's not the best way, but if you want to do it with one query (it's easy to export to Excel):
SELECT
s.Name,
s.SecondName,
DATE_FORMAT('%M %y', f.`Date`),
SEC_TO_TIME( SUM( TIME_TO_SEC( `HoursWorked` ) ) ) as TotalHours,
sum(fee) AS TotalFee
FROM
Staff AS s
INNER JOIN fee AS f on s.id = f.StaffId
WHERE
1
GROUP BY s.id, YEAR(f.`Date`), MONTH(f.`Date`)
You cal also query stuff:
// that's not a real function, just get all Staff into $staff
$staff = QueryRows(SELECT * FROM Staff);
and then query fee:
foreach($staff as $s){
// use this query to query statistics
SELECT * FROM fee
WHERE StaffId = $s['id']
GROUP BY StaffId, YEAR(f.`Date`), MONTH(f.`Date`)
}
I'm not 100% sure about this being perfect but it should definitely point you in the right direction. The AVG() function calls might be unnecessary.
SELECT
Name,
SecondName,
SUM(fee.HoursWorked) as HoursWorked,
SUM(fee.fee) as fee,
YEAR(AVG(fee.Date)) as year,
MONTH(AVG(fee.Date)) as month
FROM Staff
JOIN fee ON staff.id = fee.staffid
ORDER BY fee.Date
GROUP BY staff.id, YEAR(fee.Date), MONTH(fee.Date)
I have two tables
table_school
school_open_time|school_close_time|school_day
8:00 AM | 9:00PM | Monday
10:00 AM | 7:00PM | Wednesday
table_college
college_open_time|college_close_time|college_day
10:00 AM | 8:00PM | Monday
10:00 AM | 9:00PM | Tuesday
10:00 AM | 5:00PM | Wednesday
Now I want to select school_open_time school_close time, college_open_time and college_close_time according to today (means college_day=school_day=today), and also if there is no row for a specific day in any of one table then it display blank field ( LEFT JOIN , I think I can use).
Please suggest me best and optimized query for this.
UPDATE:
if there is no open time and close time for school then college_open_time and college_close_time has to be returned( not to be filled in database,just return) as school_open_time and school_close_time. and there always must be college_open_time and college_close_time for a given day
i m using below query
SELECT college_open_time,college_close_time ,school_open_time,
school_close_time FROM tbl_college
LEFT JOIN tbl_school ON school_owner_id=college_owner_id
WHERE college_owner_id='".$_session['user_id']."' AND
college_day='".date('l',time())."'";
it return single row (left hand having some value and right hand having blank value) when there is no row of a given day in table_school, BUT display seven rows with same value on left hand side(college_open_time, college_close_time) and 6 blank row on right hand side (school_open_time and school_close_time)
i need only one row when both table have a row of a given day
but using above query take only first row of corresponding table_school where school_owner_id is 50(let), it not see the condition that school_day name should be given day
More UPDATE #37Stars
There is a little bit problem also Dear,
datatype of school_close_time and school_open time is TIME type
whereas datatype of college_open_time and college_close_time is VARCHAR type.
i used below code given by you but i modified a bit and i m getting close to result,
but now tell me where i have to write IFNULL in below code segment
IFNULL(TIME_FORMAT()) Or TIME_FORMAT(IFNULL())
SELECT TC.owner_id,college_open_time AS collegeOpen,
college_close_time AS collegeClose,
TIME_FORMAT(school_open_time, '%h:%i %p' ) AS schoolOpen,
TIME_FORMAT(school_close_time, '%h:%i %p' ) AS schoolClose
FROM tbl_college TC
LEFT JOIN tbl_school TS ON TS.owner_id = TC.owner_id
AND TC.college_day = TS.school_day
WHERE college_day = DATE_FORMAT(NOW(),'%W')
Solution
Thanks 37stars, u r genious, thanx for the ideo of IFNULL,
i m writing OPTIMUM AND BEST QUERY
SELECT TC.owner_id,college_open_time AS collegeOpen,college_close_time AS
collegeClose, IFNULL(TIME_FORMAT(school_open_time, '%h:%i %p'),college_open_time)
AS schoolOpen,IFNULL(TIME_FORMAT(school_close_time, '%h:%i %p',college_close_time)
AS schoolClose FROM tbl_college TC LEFT JOIN tbl_school TS
ON TS.owner_id = TC.owner_id AND TC.college_day = TS.school_day
WHERE college_day = DATE_FORMAT(NOW(),'%W')
FROM tbl_storecalendar TS LEFT JOIN tbl_delivery_hours TD
ON TD.store_id = TS.store_id
AND TD.del_day = TS.dayName WHERE dayName = DATE_FORMAT( NOW( ) , '%W' )
You want a FULL OUTER JOIN, but unfortunately MySQL doesn't support this. Luckily, there is a workaround by combining a left join and a right join using UNION ALL:
Update: Changed query to answer OP's updated question.
SELECT
COALESCE(school_day, college_day) AS day,
COALESCE(school_open_time, college_open_time) AS school_open_time,
COALESCE(school_close_time, college_close_time) AS school_close_time,
COALESCE(college_open_time, school_open_time) AS college_open_time,
COALESCE(college_close_time, school_close_time) AS college_close_time
FROM (
SELECT * FROM table_school LEFT JOIN table_college ON school_day = college_day
UNION ALL
SELECT * FROM table_school RIGHT JOIN table_college ON school_day = college_day
WHERE school_day IS NULL
) AS T1
You need to add school_day = college_day to your JOIN clause.
SELECT college_open_time, college_close_time, school_open_time, school_close_time
FROM dbo.tbl_college AS TC
LEFT JOIN dbo.tbl_school AS TS ON TS.owner_id = TC.owner_id
AND TS.school_day = TC.college_day
WHERE TC.owner_id = 1
AND college_day = 'tuesday'
I would recommend changing your DB structure to two tables with the following structure:
table institutions:
institution | institution_id
table times:
institution_id | day | open_time | close_time
You could easily put your two existing tables into the new times table, i.e.
INSERT INTO times(institution, day, open_time, close_time)
SELECT 'School', school_day, school_open_time, school_close_time
FROM table_school
And then getting the query results is easy:
SELECT i.institution, t.open_time, t.close_time
FROM times t
LEFT JOIN institutions i on t.institution_id=i.institution_id
WHERE day='Wednesday'
If you want to accomplish this in one query, you'll have to use UNION to put your results together, like this:
SELECT school_open_time AS openTime,`int` AS school_close_time
FROM table_school WHERE school_day=DATE_FORMAT(NOW(),'%W')
UNION
SELECT college_open_time AS openTime,`int` AS college_close_time
FROM table_college WHERE college_day=DATE_FORMAT(NOW(),'%W');
Where DATE_FORMAT(NOW(),'%W') converts to the current day of the week.
However, this method doesn't seem all that great to me. First of all, it won't handle putting NULL methods into the result set for you in the case of a missing record. You could add some IF/ELSE statements to do this for you, but in all honesty, I'd probably just make two separate queries from your PHP code. That way, you can handle each one specifically and control your results more easily from there.