I have a table which tracks a the return code from an application. I'm trying to figure out how to format a query to return the returncode for each day into a single row. Here is the example table:
ID COMPUTER RETURNCODE DATE
-- -------- ---------- ----
1 computer1 0 May, 15 2013 00:00:00+0000
2 computer1 1 May, 16 2013 00:00:00+0000
3 computer1 1 May, 17 2013 00:00:00+0000
4 computer2 0 May, 15 2013 00:00:00+0000
5 computer2 4 May, 16 2013 00:00:00+0000
6 computer2 4 May, 17 2013 00:00:00+0000
7 computer3 0 May, 15 2013 00:00:00+0000
8 computer3 8 May, 16 2013 00:00:00+0000
9 computer3 0 May, 17 2013 00:00:00+0000
Here is the output I am trying to get with a query:
COMPUTER 2013-05-15 2013-05-16 2013-05-17
-------- ---------- ---------- ----------
computer1 0 1 1
computer2 0 4 4
computer3 0 8 0
I've created an example via sqlfiddle here:
SQL Fiddle Example: http://sqlfiddle.com/#!2/44687/1/0
Any help is appreciated!
This is called "pivoting" the data. Here is a way to do it in MySQL:
SELECT computer,
max(case when date = '2013-05-15' then returncode end),
max(case when date = '2013-05-16' then returncode end),
max(case when date = '2013-05-17' then returncode end)
FROM returncodes
group by computer
Related
I have table with id (PK,AI), name and date, when users register I set date = CURDATE().
I have a PHP page where I have to list the names where CURDATE() >= (date + 3 days) excluding weekends (Sat and Sunday) means I list names of users who completed the registration before 3 days but I don't count weekends.
which means if someone register on Monday, he should listed on the page on Thursday and if he registered on Friday, the page list him only on Wednesday (excluded weekends)
Is there any method in MySQL to accomplish this ?
Instead of doing a complex mysql query, could you not just pass in a different date to check against, depending on the weekday from your php script?
So, instead of comparing in your sql query your date+3days <= today, pass in a variable for the date offset or just calculate the date in php and pass the date in.
day of the week | offset
1 | 5
2 | 5
3 | 5
4 | 3
5 | 3
6 | 4
7 | 5
Easy in MySQL.
SELECT CURRENT_DATE + interval (3 + 2*(weekday(CURRENt_DATE) > 1)) day;
Thanks to #JamesBlond for the table, saves me to explain. ;-)
EDIT: I was confused by the (index-killing) way to request data: normally you should try taking the date from the table unmodified and to fiddle with your CURRENT_DATE data.
As long as I understand you right, it should be the following, so you also could simply use a CASE WHEN clasue, that is more readable and easier to adopt.
thedate - interval (
3 + 2*(weekday(thedate) < 3)
+ (weekday(thedate) > 4) * (weekday(thedate)-4)) DAY
AS 3_days_before
http://www.sqlfiddle.com/#!2/49731/9/0
THEDATE WEEKDAY(THEDATE) THEDATE_FORMATTED 3_DAYS_BEFORE FORMATTED_3_DAYS_BEFORE
April, 27 2014 00:00:00+0000 6 Sunday April, 22 2014 00:00:00+0000 Tuesday
April, 28 2014 00:00:00+0000 0 Monday April, 23 2014 00:00:00+0000 Wednesday
April, 29 2014 00:00:00+0000 1 Tuesday April, 24 2014 00:00:00+0000 Thursday
April, 30 2014 00:00:00+0000 2 Wednesday April, 25 2014 00:00:00+0000 Friday
May, 01 2014 00:00:00+0000 3 Thursday April, 28 2014 00:00:00+0000 Monday
May, 02 2014 00:00:00+0000 4 Friday April, 29 2014 00:00:00+0000 Tuesday
May, 03 2014 00:00:00+0000 5 Saturday April, 29 2014 00:00:00+0000 Tuesday
May, 04 2014 00:00:00+0000 6 Sunday April, 29 2014 00:00:00+0000 Tuesday
May, 05 2014 00:00:00+0000 0 Monday April, 30 2014 00:00:00+0000 Wednesday
May, 06 2014 00:00:00+0000 1 Tuesday May, 01 2014 00:00:00+0000 Thursday
May, 07 2014 00:00:00+0000 2 Wednesday May, 02 2014 00:00:00+0000 Friday
I have the following tables:
http://sqlfiddle.com/#!2/1e991/1
But I have a problem! The output of my query is:
DATE SLOT sum(SUCCESSFUL) SUCCESSFUL PERCENTAGE OTA_NAME USERS_SI
July, 02 2013 00:00:00+0000 2 120 120 41.6667 campana 2 50
July, 02 2013 00:00:00+0000 1 200 200 25 campana 2 50
July, 02 2013 00:00:00+0000 1 150 150 53.3333 campana 3 80
July, 01 2013 00:00:00+0000 2 100 100 20 campana 1 20
July, 01 2013 00:00:00+0000 3 440 440 4.5455 campana 1 20
July, 01 2013 00:00:00+0000 1 700 700 2.8571 campana 1 20
And I need a sum of successful with the same date and campaign, for example, I have in July 1 with campaign 1 three rows, then I need sum the successful of the three rows, and with campaign 2 two rows, then I need sum the successful of the two rows, and with campaign 3 one rows, then I need sum the successful of the one row that is the same.
And finally the percentage is the division between sum(SUCCESSFUL) and USERS_SI
The output that I need is:
DATE SLOT sum(SUCCESSFUL) SUCCESSFUL PERCENTAGE OTA_NAME USERS_SI
July, 02 2013 00:00:00+0000 2 320 120 41.6667 campana 2 50
July, 02 2013 00:00:00+0000 1 320 200 25 campana 2 50
July, 02 2013 00:00:00+0000 1 150 150 53.3333 campana 3 80
July, 01 2013 00:00:00+0000 2 1240 100 20 campana 1 20
July, 01 2013 00:00:00+0000 3 1240 440 4.5455 campana 1 20
July, 01 2013 00:00:00+0000 1 1240 700 2.8571 campana 1 20
Can you help me?
sqlfiddle here
SELECT other.date AS date,
other.slot,
other.successful,
calc.sum_successful,
max((case when (rule.tree_si = dms.tree) then dms.numberResponses end))/successful AS percentage,
other.name AS ota_name,
other.successful AS successful,
max((case when (rule.tree_si = dms.tree) then dms.numberResponses end)) AS users_si
FROM aca_ota_other other
join aca_dms_rules rule on other.name = rule.ota_name
join aca_dms dms on dms.date = other.date and rule.tree_si = dms.tree
join (SELECT name, sum(successful) as sum_successful FROM aca_ota_other GROUP BY name) as calc on other.name = calc.name
GROUP BY
other.date,
other.name,
other.successful
ORDER BY other.date desc
I'm not sure but if i understood well, you need something like this:
I'm sorry, I've made some little changes in your query.
SELECT other.date date,
other.slot,
other.name ota_name,
sum(successful) successful,
dms.numberResponses users_si,
SUM(successful)/dms.numberResponses AS percentage
FROM aca_ota_other other
JOIN aca_dms_rules rule ON other.name=rule.ota_name
JOIN aca_dms dms ON dms.date=other.date AND rule.tree_si=dms.tree
GROUP BY other.date,
other.name
ORDER BY other.date DESC
http://sqlfiddle.com/#!2/1e991/22
I am trying to get some help fixing my complex query. I am explaining below my situation, thanks.
I have the following two tables:
ACTIVITY TABLE:
ID USER_ID CARD_ID CLOCK
1 123 04675545 4/3/2013 1:07:06 PM
2 123 04675545 4/3/2013 2:08:06 PM
3 124 04675550 4/3/2013 2:07:06 PM
4 124 04675550 4/3/2013 4:07:06 PM
5 124 04675550 4/4/2013 10:07:06 AM
6 124 04675550 4/4/2013 2:00:00 PM
7 124 04675550 4/5/2013 4:07:06 PM
8 124 04675550 4/7/2013 8:00:00 AM
9 124 04675550 4/7/2013 5:00:00 PM
PRICE TABLE:
ID FROMTIME TOTIME PRICEPERHOUR
1 08:00:00 19:59:59 50.00
2 20:00:00 07:59:59 75.00
And the following query:
select a.user_id, date(a.clock), ABS(TIME_TO_SEC(TIMEDIFF(a.clock, b.clock))/3600)*c.PRICEPERHOUR as total from
(Select if((#rn:=#rn+1)%2=0,#rn,#rn-1) As rId, act.* from act
join (select #rn:=-1)a
order by user_Id, clock) a
inner join
(Select if((#rn1:=#rn1+1)%2=0,#rn1,#rn1-1) As rId, act.* from act
join
(select #rn1:=-1)b
order by user_Id, clock) b
ON a.rid=b.rid AND a.id <> b.id
inner join
price c
on
TIME_TO_SEC(a.clock) between TIME_TO_SEC(c.FROMTIME)
AND
TIME_TO_SEC(c.TOTIME)
group by a.user_id, date(a.clock)
And I am getting the following result:
USER_ID DATE(A.CLOCK) TOTAL
123 April, 03 2013 00:00:00+0000 50.8333
124 April, 03 2013 00:00:00+0000 100
124 April, 04 2013 00:00:00+0000 194.0833
124 April, 05 2013 00:00:00+0000 1,994.0833
124 April, 07 2013 00:00:00+0000 1,994.0833
However, I am trying to get this result instead:
USER_ID DATE(A.CLOCK) TOTAL
123 April, 03 2013 00:00:00+0000 50.8333
124 April, 03 2013 00:00:00+0000 100
124 April, 04 2013 00:00:00+0000 194.0833
124 April, 05 2013 00:00:00+0000 50
124 April, 07 2013 00:00:00+0000 450
This is part of a clock system. Each time the user check-in, one entry gets recorded on the database. A correct user behavior will be that it has always a pair record recorded. For example user_id 123 clocks at 1:07:06pm and clocks again at 2:08:06pm. However, in some situations, the user may do it just once (unpaired record on the database) and therefore it should only be charged that particular hour from the record. As an example, user 124 on day 4/5/2013.
I am trying all weekend to get this query working :(. Once I get the correct result, I will add a condition to get only one user_id also, (e.g. where user_id=124).
I think even if you manage to do this there are are some potential design pitfalls:
Can people clock in for more than 1 period per day? If so then 2 records for example
10am and 2pm could total 2hours or 4hours.
What happens if people clock in at 11pm and again at 2am?
From a quick glance I don't think your sql takes into account time periods that span across the 2 different pay rates? You should definitely include this scenario in your test data.
If I was going to implement this I would probably move the logic into code, and simplify the price table by only having one time column like:
TIME, PRICE
00:00, 75.00
08:00, 50.00
20:00, 75.00
Also if a user only has one card you may not need to have card_id and user_id in the activity table.
I have output as below
ID Date
Null 2012-10-01
1 2012-10-02
2 2012-10-03
NULL 2012-10-04
3 2012-10-05
NULL 2012-10-06
4 2012-10-07
NULL 2012-10-08
5 2012-10-10
NULL 2012-10-11
NULL 2012-10-12
6 2012-10-13
NULL 2012-10-16
As it has missing dates with value as NULL. I need to show final output as
2012-10-01 - 2012-10-01 (1 day )
2012-10-04 - 2012-10-04(1 day )
2012-10-06 - 2012-10-06(1 day )
2012-10-08 - 2012-10-08(1 day )
2012-10-11 - 2012-10-12(2 day )
2012-10-14 - 2012-10-14(1 day )
You can generate the date ranges using the following query:
select
min(date) as start,
max(date) as end,
datediff(max(date), min(date)) + 1 as numDays
from
(select #curRow := #curRow + 1 AS row_number, id, date
from Table1 join (SELECT #curRow := 0) r where ID is null) T
group by
datediff(date, '2012-10-01 00:00:00') - row_number;
The logic is based on a clever trick for grouping consecutive ranges. First, we filter and number the rows in the subquery. Then, the rows that are grouped together are found by comparing the number of days after 2012-10-01 to the row number. If any rows share this value, then they must be consecutive, otherwise there would be a "jump" between two rows and the expression datediff(date, '2012-10-01 00:00:00') - row_number would no longer match.
Sample output (DEMO):
START END NUMDAYS
October, 01 2012 00:00:00+0000 October, 01 2012 00:00:00+0000 1
October, 04 2012 00:00:00+0000 October, 04 2012 00:00:00+0000 1
October, 06 2012 00:00:00+0000 October, 06 2012 00:00:00+0000 1
October, 08 2012 00:00:00+0000 October, 08 2012 00:00:00+0000 1
October, 11 2012 00:00:00+0000 October, 12 2012 00:00:00+0000 2
October, 16 2012 00:00:00+0000 October, 16 2012 00:00:00+0000 1
From there I think it should be pretty trivial for you to get the exact output you are looking for.
I have database dbadmin, table - tbl_empreimburse with fields-emp_id,rem_amount,rem_date.
I want to retrieve data which comes from given date to a week back.
I tried this query,
SELECT SUM(rem_amount),DATEADD(dd, -7, "2012-01-10")
FROM tbl_empreimburse
GROUP BY emp_id
HAVING emp_id='5' AND rem_date BETWEEN DATEADD(dd, -7, "2012-01-10") AND "2012-01-10"
It gives me error "FUNCTION dbadmin.DATEADD does not exist". Do I need to convert "2012-01-10" to date format? Any Help, Please?
Try this:
This query gives result as you have specified for employee id 5 and date period of 7 days.
SELECT emp_id, SUM(rem_amount)
FROM tbl_empreimburse
WHERE emp_id='5' AND DATEDIFF('2012-12-31', rem_date) BETWEEN 0 AND 7;
OR
Below query gives you all employee data.
SELECT emp_id, SUM(rem_amount)
FROM tbl_empreimburse
GROUP BY emp_id
HAVING DATEDIFF('2012-12-31', rem_date) BETWEEN 0 AND 7;
Check this *SQLFIDDLE reference out. :)
I am not sure why you are using group by clause here...
Sample date:
ID AMOUNT RDATE
1 3400 January, 01 2012 00:00:00+0000
2 5000 January, 10 2012 00:00:00+0000
3 3000 January, 02 2012 00:00:00+0000
5 1000 January, 05 2012 00:00:00+0000
5 2000 January, 04 2012 00:00:00+0000
2 2000 February, 10 2012 00:00:00+0000
Query:
select * from emp
where id = 5;
here is the query to get sum
select id, sum(amount)
from emp
where rdate between '2012-01-10' - interval 7 day
and '2012-01-10'
and id = 5
;
Results:
all records by employee id = 5
ID AMOUNT RDATE
5 1000 January, 05 2012 00:00:00+0000
5 2000 January, 04 2012 00:00:00+0000
sum of amount by employee id = 5
ID SUM(AMOUNT)
5 3000