I have a simple database (using MySql) with which I need to generate a report.
I have a table that schedule_plan which are submitted by users.
and my table userinfo which contain name ,age dll
So I need a report which displays the days as columns as well as the names from a userinfo table.
Report
+------+--------+--------+--------+-------+
| Name | 1 | 2 | 3 | until day 30/31 |
+------+--------+--------+--------+-------+
| Bob | ON | ON | ON | ... |
| Joe | OFF | ON | OFF | ... |
| Jim | ON | ON | ON | ... |
if absence_code in schedule_plan is null then ON if not null OFF
create table attendance
(user_id int,attendance_code varchar(1),dte date)
*/
truncate table attendance;
insert into attendance values
(1,'a','2016-01-01'),
(1,null,'2016-01-02'),
(1,'a','2016-01-03'),
(1,'a','2016-01-04'),
(1,'a','2016-01-05'),
(2,'a','2016-01-01'),
(2,'a','2016-01-02'),
(2,null,'2016-01-03'),
(2,null,'2016-01-04'),
(2,'a','2016-01-05')
;
select a.user_id,
max(case when day(a.dte) = 1 then case when a.attendance_code is not null then 'On' else 'Off' end end) as day1,
max(case when day(a.dte) = 2 then case when a.attendance_code is not null then 'On' else 'Off' end end) as day2,
max(case when day(a.dte) = 3 then case when a.attendance_code is not null then 'On' else 'Off' end end) as day3,
max(case when day(a.dte) = 4 then case when a.attendance_code is not null then 'On' else 'Off' end end) as day4,
max(case when day(a.dte) = 5 then case when a.attendance_code is not null then 'On' else 'Off' end end) as day5
from attendance a
group by a.user_id;
Related
I have some MySQL records generated by a view:
+---------+-----------------------------+------------+
| user_id | meta_key | meta_value |
+---------+-----------------------------+------------+
| 2 | admin-first-timer-training | NULL |
| 2 | admin-first-timer-overnight | No |
| 2 | admin-first-timer-outdoor | No |
+---------+-----------------------------+------------+
I want to have the records:
+---------+-----------------------------+------------+
| user_id | meta_key | meta_value |
+---------+-----------------------------+------------+
| 2 | admin-first-timer-training | Yes |
| 2 | admin-first-timer-overnight | No |
| 2 | admin-first-timer-outdoor | No |
+---------+-----------------------------+------------+
Currently I'm generating these records with this view:
create VIEW `wp_record_db` AS
select distinct `u`.`ID` AS `id`,
(select distinct (
CASE WHEN `wp_usermeta`.`meta_value`="No" THEN "No"
ELSE "Yes" END)
from `wp_usermeta`
where `wp_usermeta`.`user_id` = `u`.`ID` and `wp_usermeta`.`meta_key` in ('admin-first-timer-outside','admin-first-timer-outdoors','admin-first-timer-outdoor')
limit 1) AS `admin-first-timer-outdoor`,
(select distinct (
CASE WHEN `wp_usermeta`.`meta_value`="No" THEN "No"
WHEN `wp_usermeta`.`meta_value` IS NULL THEN "YES"
ELSE "Yes" END)
from `wp_usermeta` where `wp_usermeta`.`user_id` = `u`.`ID` and `wp_usermeta`.`meta_key` = 'admin-first-timer-training'
limit 1) AS `admin-first-timer-training`,
(select distinct (
CASE WHEN `wp_usermeta`.`meta_value`="No" THEN "No"
ELSE "Yes" END)
from `wp_usermeta`
where `wp_usermeta`.`user_id` = `u`.`ID` and `wp_usermeta`.`meta_key` = 'admin-first-timer-overnight'
limit 1) AS `admin-first-timer-overnight`
from `wp_users` `u`;
As you can see in
(select distinct (CASE WHEN `wp_usermeta`.`meta_value`="No" THEN "No" WHEN `wp_usermeta`.`meta_value` IS NULL THEN "YES" ELSE "Yes" END) from `wp_usermeta` where `wp_usermeta`.`user_id` = `u`.`ID` and `wp_usermeta`.`meta_key` = 'admin-first-timer-training' limit 1) AS `admin-first-timer-training`,
I've been trying to test whether it's NULL using a Case statement, however that isn't providing the desired result.
SELECT IFNULL((select `wp_usermeta`.`meta_value` from `wp_usermeta` where `wp_usermeta`.`user_id` = 2 and `wp_usermeta`.`meta_key` = 'admin-first-timer-training'), "Yes");
Is as close as I've got - as this does seem to produce the desired return output, but I can't make it work in a Case statement - however I try and insert it, it always returns an Empty Statement.
What can I try?
You can use conditional aggregation to make the query metter readable
But NULL will always be different from No so , you don't need extra checking for NULL
SELECT
`user_id`,
MIN(CASE WHEN `meta_key` = 'admin-first-timer-training' AND `meta_value` = 'No' THEn 'No' ELSE 'Yes' END) as 'admin-first-timer-training',
MIN(CASE WHEN `meta_key` = 'admin-first-timer-overnight' AND `meta_value` = 'No' THEn 'No' ELSE 'Yes' END) as 'admin-first-timer-overnight',
MIN(CASE WHEN `meta_key` = 'admin-first-timer-outdoor' AND `meta_value` = 'No' THEn 'No' ELSE 'Yes' END) as 'admin-first-timer-outdoor'
FROM wp_usermeta
GROUP BY user_id
user_id | admin-first-timer-training | admin-first-timer-overnight | admin-first-timer-outdoor
------: | :------------------------- | :-------------------------- | :------------------------
2 | Yes | No | No
db<>fiddle here
I want to get the total maximum number of column CODE which the maximum is defined by the last five digits from mybarcode column.
mybarcode | code | judge | create_date |
-------------+------+--------+-------------+
M71X400001 | 7 | pass |
M71X400002 | 7 | pass |
M71X400005 | 7 | pass |
M71X400010 | 7 | pass |
M81X400001 | 8 | pass |
M81X400002 | 8 | pass |
M81X400007 | 8 | pass |
M91X400001 | 9 | pass |
M91X400003 | 9 | pass |
```
Example:
>The maximum value of 7 from CODE column is 10 ( from M71X4'00010')
>The maximum value of 8 from CODE column is 7 ( from M81X4'00007')
>The maximum value of 9 from CODE column is 3 ( from M91X4'00003')
The result should be 10+7+3=20.
And want display in the result table below.
```
SELECT DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail
**??? as number**
from MYTABLE
where MONTH(create_date) = '04' and YEAR(create_date) = '2019'
GROUP BY DAY
Result Table
day | pass | fail | number |
--------+------+--------+----------+
1 | 9 | 0 | 20 |
2 | 9 | 0 | ?? |
3 | 9 | 0 | ?? |
I think you need to do group by two times. Please try below code -
For MySQL -
SELECT
DAY,
SUM(pass),
SUM(fail),
SUM(max_barcode)
FROM (
SELECT
DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail,
Code,
CAST(MAX(SUBSTRING(mybarcode, 5)) AS SIGNED) AS max_barcode
FROM MYTABLE
WHERE MONTH(create_date) = '%s' and YEAR(create_date) = '%s'
GROUP BY DAY, Code
) AS CTE
GROUP BY DAY;
FOR MS SQL Server -
;WITH CTE AS (
SELECT
DAY,
SUM(CASE WHEN judge = 'pass' then 1 else 0 end) pass,
SUM(CASE WHEN judge = 'fail' then 1 else 0 end) fail,
Code,
max_barcode = cast(max(right(mybarcode, 5)) as int)
FROM MYTABLE
WHERE MONTH(create_date) = '%s' and YEAR(create_date) = '%s'
GROUP BY DAY, Code
)
SELECT
DAY,
SUM(pass),
SUM(fail),
SUM(max_barcode)
FROM CTE
GROUP BY DAY;
Using information of this site I have been able to do the join but im having the issues doing the group by
is there a way to get the below statements to run as 1
Query1
SELECT count(location),date
from `filter`
where location != "red"
group by date
Query2
SELECT count(location),date
from `filter`
where location = "red"
group by date
I did try the below but it outputs the wrong data
Query3
SELECT
date,
(select count(location) from `filter` where location != "red") AS indoor,
(select count(location) from `filter` where location = "red") AS outdoor
from `filter` group by date;
SQL Fiddle for each query
http://sqlfiddle.com/#!9/17ebea/4 (query1)
http://sqlfiddle.com/#!9/17ebea/6 (query2)
http://sqlfiddle.com/#!9/90c945/1 (query3)
SELECT
date,
COUNT(CASE WHEN location <> 'red' THEN location ELSE NULL END) AS indoor,
COUNT(CASE WHEN location = 'red' THEN location ELSE NULL END) AS outdoor
FROM filter
GROUP BY date;
https://dev.mysql.com/doc/refman/8.0/en/control-flow-functions.html#operator_case
You can do conditional aggregation using CASE.. WHEN expressions.
SELECT
date,
COUNT(CASE WHEN location = 'red' THEN location END) AS outdoor,
COUNT(CASE WHEN location <> 'red' THEN location END) AS indoor
FROM `filter`
GROUP BY date;
View on DB Fiddle
Result
| date | outdoor | indoor |
| ---------- | ------- | ------ |
| 2018-11-14 | 1 | 4 |
| 2018-11-15 | 1 | 0 |
| 2018-11-16 | 0 | 3 |
| 2018-11-17 | 1 | 1 |
| 2018-11-18 | 0 | 1 |
| 2018-11-19 | 0 | 2 |
| 2018-11-20 | 0 | 1 |
You can also use the following other variants, like using COUNT(1) instead, or using SUM(..) function.
Alternative #1
SELECT
date,
COUNT(CASE WHEN location = 'red' THEN 1 END) AS outdoor,
COUNT(CASE WHEN location <> 'red' THEN 1 END) AS indoor
FROM `filter`
GROUP BY date;
Alternative #2
SELECT
date,
SUM(CASE WHEN location = 'red' THEN 1 ELSE 0 END) AS outdoor,
SUM(CASE WHEN location <> 'red' THEN 1 ELSE 0 END) AS indoor
FROM `filter`
GROUP BY date;
In MySQL, I would use the shortcut that allows you to sum() boolean variables:
select date, sum(location = 'red') as red,
sum(location <> 'red') as not_red
from filter
group by date ;
Notes:
Use single quotes for string and date constants -- not double quotes. Single quotes are the standard delimiter.
<> is the SQL inequality operator, although != is also supported by most databases.
This does not count NULL values.
To handle NULL values, you might want:
sum(not location <=> 'red') as not_red
This is my table:
id | num | comment
---+-----+--------
3 | 10 | hello
3 | 20 | pls
3 | 30 | respond
7 | 10 | leet
7 | 20 | hax
7 | 30 | zor
How can I query it out in this manner:
id | first | second | third
---+-------+--------+--------
3 | hello | pls | respond
7 | leet | hax | zor
In the event that the num column does not reliably always start at 10 and ascend by 10 you can use the following to establish a row number that restarts at each change in ID, that way you can use the rownumbers in conjunction with conditional aggregation to show each comment. The following would do so for up to 10 comments per ID, and the NUM column does not have to be 10/20/30/40/50/60/70/80/90 (it could be anything).
If the NUM column reliably starts at 10 and ascends by 10, this question has been asked and answered: How to pivot rows into columns (custom pivoting)
select id,
max(case when row_number = 1 then comment else null end) as c01,
max(case when row_number = 2 then comment else null end) as c02,
max(case when row_number = 3 then comment else null end) as c03,
max(case when row_number = 4 then comment else null end) as c04,
max(case when row_number = 5 then comment else null end) as c05,
max(case when row_number = 6 then comment else null end) as c06,
max(case when row_number = 7 then comment else null end) as c07,
max(case when row_number = 8 then comment else null end) as c08,
max(case when row_number = 9 then comment else null end) as c09,
max(case when row_number = 10 then comment else null end) as c10
from(
select #row_number := case when #prev_val = id then #row_number+1 else 1 end as row_number,
id,
comment,
#prev_val:=id as prev_val
from tbl, (select #row_number:=0,#prev_val:='') x
order by id, num) x
group by id
order by id
i would create a particular sql string.
I have this tables :
cities
-----------
city varchar not null primary key
etc
weeks
-----------
week varchar not null primary key
Insert_data
-----------
id int not null primary key
cityID varchar
week varchar
value1 int
etc
I would to bind asp.net gridview with this table structure:
+-----+-------+-------+-------+
| city| week1 | week2 | week3 |
+-----+-------+-------+-------+
| 1 | (y/n) | (y/n) | (y/n) |
| 2 | (y/n) | (y/n) | (y/n) |
| 3 | (y/n) | (y/n) | (y/n) |
| 4 | (y/n) | (y/n) | (y/n) |
| 5 | (y/n) | (y/n) | (y/n) |
+----+-------+-------+-------+
if there are records related to that week in insert_data the value will be Y.
It's possible to create a query string for this?
As always, when you need to create columns from rows with a "group by argument" (city), you can use the PIVOT operator.
http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
Above only applies to MS-SQL, doesn't apply to MySQL.
Or you can do it the old-fashioned way
SELECT
cities.city
,SUM(CASE WHEN weeks.week = 1 THEN Insert_data.value1 ELSE 0 END) AS week1
,SUM(CASE WHEN weeks.week = 2 THEN Insert_data.value1 ELSE 0 END) AS week2
,SUM(CASE WHEN weeks.week = 3 THEN Insert_data.value1 ELSE 0 END) AS week3
,SUM(CASE WHEN weeks.week = 4 THEN Insert_data.value1 ELSE 0 END) AS week4
-- ,etc. for each week (select distinct week from insert_data order by week)
FROM Insert_data
left join cities
cities.city= Insert_data.cityID
left join weeks
on weeks.week = Insert_data.week
group by cities.city
Either way, you need to dynamically hardcode the weeks in your SQL string.
You would now need an additional condition for y and n, and then you can concat the values.
,'(' + CAST(SUM(CASE WHEN weeks.week = 1 AND value1 = 1 THEN 1 ELSE 0 END) as varchar(10))
+ '/'
CAST(SUM(CASE WHEN weeks.week = 1 AND value1 = 0 THEN 1 ELSE 0 END) as varchar(10))
+ ')'
AS week1
or if it's just y or no, then
,
CASE
WHEN SUM(CASE WHEN weeks.week = 1 THEN Insert_data.value1 ELSE 0 END) > 0
THEN 'y'
ELSE 'n'
END AS week1