Can anyone help me to group 2 tables and show like below...
My first table is :
user_id | department
-----------------------
1 | user1
----------------------
2 | user2
----------------------
and table 2 is :
reserve_id | user_id | reserve_status
--------------------------------------
1 | 1 | 1
--------------------------------------
2 | 1 | 1
--------------------------------------
3 | 1 | 2
--------------------------------------
4 | 2 | 2
--------------------------------------
5 | 2 | 0
--------------------------------------
6 | 2 | 1
*reserve_status 0 uncheck, 1 = approve , 2 = disapproval
I want product like this :
department | sumreserve | sumreservapprove | sumreserveunapprove | uncheck
----------------------------------------------------------------------------
user1 | 3 | 2 | 1 | 0
----------------------------------------------------------------------------
user2 | 3 | 1 | 1 | 1
Sorry for poor in English
You require a pivot solution.
Demo:
Assuming so_q27895250_users and so_q27895250_reserve as table names
mysql>
mysql> select u.department, count(r.reserve_status) as total_reserves,
-> count( case when r.reserve_status = 0
-> then r.reserve_status else null end ) as unchecked,
-> count( case when r.reserve_status = 1
-> then r.reserve_status else null end ) as approved,
-> count( case when r.reserve_status = 2
-> then r.reserve_status else null end ) as unapproved
-> from so_q27895250_reserve r
-> left join so_q27895250_users u
-> on r.user_id = u.user_id
-> group by r.user_id
-> ;
+------------+----------------+-----------+----------+------------+
| department | total_reserves | unchecked | approved | unapproved |
+------------+----------------+-----------+----------+------------+
| user1 | 3 | 0 | 2 | 1 |
| user2 | 3 | 1 | 1 | 1 |
+------------+----------------+-----------+----------+------------+
2 rows in set (0.00 sec)
Related
I have a pivot table with the respective fields.
district
block
MaleCount
FemaleCount
above are a column name. So, basically, I have grouped all those fileds by district and block-wise. For that, I have written the following query in MySQL.
select
ds.ds_name as district,
bs.bl_name as block,
case
when sd.gender_id = 1 then count(gender_id)
else 0
end as MaleCount,
case
when sd.gender_id = then count(gender_id)
else 0
end as FemalCount,
from studet data sd
inner join district ds on ds.district_id = sd.ds_id
inner join block bs on bs.block_id = sd.bs_id
group by bs.block_name, ds.district_name;
which gives the following result
district | block | FemalCount | MaleCount
xyz | abc | 4 | 5
| cvz | 5 | 9
ytz | tyz | 7 | 3
| awe |3 |8
The main thing is, I want the following kind of the result set.
district | block | FemalCount | MaleCount
xyz | abc | 4 | 5
| cvz | 5 | 9
total | | 9 | 14
ytz | tyz | 7 | 3
| awe | 3 | 8
total | | 10 | 11
which includes a subtotal row for Malecount and FemaleCount with a group by block and district as mention above. How could I achieve this in MySQL query?
You could add a union all (with high values for the block name to push it to the end on the order by) to calculate the totals by district so given
+----------+-----------+-------+-------+
| sudentid | gender_id | ds_id | bs_id |
+----------+-----------+-------+-------+
| 101 | 2 | 3 | 2 |
| 103 | 2 | 3 | 2 |
| 112 | 1 | 3 | 3 |
| 116 | 1 | 3 | 3 |
| 117 | 1 | 3 | 3 |
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 1 | 1 | 1 |
+----------+-----------+-------+-------+
8 rows in set (0.00 sec)
DROP TABLE IF EXISTS DISTRICT,BLOCK;
CREATE TABLE DISTRICT (ID INT, name varchar(10));
create table block(id int, name varchar(10));
insert into district values (1,'aaa'),(2,'bbb'),(3,'ccc'),(4,'ddd');
insert into block values (1,'E'),(2,'F'),(3,'G');
select
case when block = 'zzz' then 'Total'
else district
end as district,
case when block = 'zzz' then ''
else block
end as block,
malecount,femalecount
from
(
select
ds.name as district,
bs.name as block,
sum(case when gender_id = 1 then 1 else 0 end) Malecount,
sum(case when gender_id = 2 then 1 else 0 end) Femalecount
from student sd
inner join district ds on ds.id = sd.ds_id
inner join block bs on bs.id = sd.bs_id
group by ds.name, bs.name
union all
select district,'zzz', malecount,femalecount
from
(
select ds.name as district,
sum(case when gender_id = 1 then 1 else 0 end) Malecount,
sum(case when gender_id = 2 then 1 else 0 end) Femalecount
from student sd
inner join district ds on ds.id = sd.ds_id
group by ds.name
) s
) t
order by t.district,t.block
;
Result
+----------+-------+-----------+-------------+
| district | block | malecount | femalecount |
+----------+-------+-----------+-------------+
| aaa | E | 3 | 0 |
| Total | | 3 | 0 |
| ccc | F | 0 | 2 |
| ccc | G | 3 | 0 |
| Total | | 3 | 2 |
+----------+-------+-----------+-------------+
5 rows in set (0.00 sec)
Note the slightly less verbose conditional aggregation (sum(case when...)
I am trying to create a chat app, and I wanted to pull up the conversation of user 1 and 2.
Table:
+----+---------------------+-----------+---------+
| id | message | from_user | to_user |
+----+---------------------+-----------+---------+
| 1 | hello trick | 1 | 2 |
| 2 | hi raf i am okay | 2 | 1 |
| 3 | how is jo doing | 1 | 2 |
| 4 | Hey | 2 | 3 |
| 5 | she is doing well | 2 | 1 |
| 6 | how is kc doing | 2 | 1 |
+----+---------------------+-----------+---------+
This is my failed query:
mysql> SELECT *
-> FROM Messages
-> WHERE from_user = 1
-> AND to_user = 2
-> AND to_user = 1
-> AND from_user = 2;
Empty set (0.00 sec)
How do I achieve selecting conversation of user 1 and 2. Is my design efficient for a chat application?
Expected Output:
+----+---------------------+-----------+---------+
| id | message | from_user | to_user |
+----+---------------------+-----------+---------+
| 1 | hello trick | 1 | 2 |
| 2 | hi raf i am okay | 2 | 1 |
| 3 | how is jo doing | 1 | 2 |
| 5 | she is doing well | 2 | 1 |
| 6 | how is kc doing | 2 | 1 |
+----+---------------------+-----------+---------+
ORDER BY id may be necessary
This should do it.
SELECT *
FROM Messages
WHERE (from_user = 1 AND to_user = 2)
OR (from_user = 2 AND to_user = 1);
mysql> SELECT *
-> FROM Messages
-> WHERE from_user in (1 , 2)
-> AND to_user in (1, 2);
A single row can't have both to_user=1 and to_user=2, so this query will return no rows. Instead, you need to use the logical or operator to separate between both "directions" of the conversation:
SELECT *
FROM messages
WHERE (from_user = 1 AND to_user = 2) OR (to_user = 1 AND from_user = 2)
I have 4 tables as a bellow
table : user
id_tkn | nm_user |
-----------------------------------------
1 | belva |
2 | nanda |
3 | maya |
-----------------------------------------
table : maintenance
id_mntnc|id_tkn | sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 2 | 2 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
4 | 2 | 0 |2016-03-03 |
5 | 2 | 1 |2016-03-03 |
-----------------------------------------------------------------
table : Installasi
id_istlsi|id_tkn| sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 1 | 1 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
4 | 2 | 1 |2016-03-03 |
5 | 3 | 1 |2016-03-03 |
-----------------------------------------------------------------
table : visit
id_vst |id_tkn | sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 2 | 0 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
-----------------------------------------------------------------
information about 'sts' column
0 --> Pending
1 --> Success
2 --> Fail.
from the table above,I want to add up by status(sts) where id_tkn = 2,the result like table below,how to generate SQL command to produce the table below ?
id_tkn | nm_usr | maintenance_suc | maintenance_fail | installasi_suc| installasi_fail | visit_suc| visit_fail
-----------------------------------------------------------------------------------------------------------------------
2 | nanda | 2 | 1 | 2 | 0 | 1 | 0
This should work right, but probably need to be optimized:
select
u.id_tkn,
u.nm_user,
sum ( case when stat.sts = 1 and stat.typ = 'm' then 1 else 0 end ) as maintenance_suc,
sum ( case when stat.sts = 2 and stat.typ = 'm' then 1 else 0 end ) as maintenance_fail,
sum ( case when stat.sts = 1 and stat.typ = 'i' then 1 else 0 end ) as installasi_suc,
sum ( case when stat.sts = 2 and stat.typ = 'i' then 1 else 0 end ) as installasi_fail,
sum ( case when stat.sts = 1 and stat.typ = 'v' then 1 else 0 end ) as visit_suc,
sum ( case when stat.sts = 2 and stat.typ = 'v' then 1 else 0 end ) as visit_fail
from
user u
left join
(
select sts, 'm', id_tkn
from
maintenance
union all
select sts, 'i', id_tkn
from
Installasi
union all
select sts, 'v', id_tkn
from
visit
) stat on u.id_tkn = stat.id_tkn
where u.id_tkn = 2
group by u.id_tkn, u.nm_user
I have a table which store user votes, something like this:
+----+---------+-------+---------+
| id | post_id | value | user_id |
+----+---------+-------+---------+
| 1 | 103 | 1 | 1 |
| 2 | 105 | 1 | 3 |
| 3 | 106 | 1 | 1 |
| 4 | 108 | 0 | 1 |
| 5 | 108 | 0 | 2 |
| 6 | 105 | 0 | 2 |
| 7 | 105 | 1 | 1 |
+----+---------+-------+---------+
Where id is Vote ID, post_id is Post ID, value is a boolean for like/unlike (1 = Like, 0 = Unlike) and user_id is Voter ID.
I want to get a list which has:
All posts
Each post's like count
Each post's unlike count
Vote ID of where a user (for example, user 1) voted. So I can update the value later
The vote that user gave
So I wrote this query:
SELECT
post_id,
COUNT(
CASE
WHEN value = 1
THEN 1
END
) AS likes,
COUNT(
CASE
WHEN value = 0
THEN 1
END
) AS unlikes,
(CASE
WHEN user_id = 1 -- I choose user_id manually
THEN id
END) AS vote_id,
(CASE
WHEN user_id = 1
THEN value
END) AS user_vote
FROM votes
GROUP BY post_id;
What I expected was something like this:
+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
| 103 | 1 | 0 | 1 | 1 |
| 105 | 2 | 1 | 7 | 1 |
| 106 | 1 | 0 | 3 | 1 |
| 108 | 0 | 2 | 4 | 0 |
+---------+-------+---------+---------+-----------+
But this is the result I have:
+---------+-------+---------+---------+-----------+
| post_id | likes | unlikes | vote_id | user_vote |
+---------+-------+---------+---------+-----------+
| 103 | 1 | 0 | 1 | 1 |
| 105 | 2 | 1 | NULL | NULL |
| 106 | 1 | 0 | 3 | 1 |
| 108 | 0 | 2 | 4 | 0 |
+---------+-------+---------+---------+-----------+
Those NULL values happen because of the last line of my query (GROUP BY post_id). If there's a duplicate post_id in table (for example, if some other user already voted for that post), CASE will ignore it and return NULL.
What should I do?
The problem with your query is the lack of aggregations on the last two columns. Assuming that a user can only vote once for a post, you are safe combining the values using MAX() (or MIN()) because there is at most one matching row:
SELECT v.post_id, SUM(value = 1) AS likes, SUM(value = 0) AS unlikes,
MAX(CASE WHEN user_id = 1 THEN vote_id END) AS user1_voteid,
MAX(CASE WHEN user_id = 1 THEN value END) AS user1_vote
FROM votes v
GROUP BY v.post_id;
I have two tables.
I want to select 1 record from first table if
condition is true in second table (active = 0)
table Lead:
-------------
| id | name |
-------------
| 1 | abc1 |
| 2 | abc2 |
| 3 | abc3 |
| 4 | abc4 |
| 5 | abc5 |
-------------
table LeadsDetails:
-------------------------
| id | lead_id | active |
-------------------------
| 1 | 1 | 1 |
| 2 | 1 | 0 |
| 3 | 2 | 0 |
| 4 | 3 | 1 |
| 5 | 4 | 0 |
| 6 | 5 | 0 |
| 7 | 5 | 0 |
--------------------------
expected output:
--------------
| id | name |
--------------
| 2 | abc2 |
| 4 | abc4 |
| 5 | abc5 |
--------------
SELECT `Lead`.`id`, `Lead`.`name`, `Lead`.`unsubscribe`
FROM `leads` AS `Lead` inner JOIN `LeadsDetails` AS `LeadsDetails`
ON (`LeadsDetails`.`lead_id` = `Lead`.`id`)
WHERE `LeadsDetails`.`active` = 0
This should run faster than not exists because the subquery won't run for every row; in this case I'm counting the number of situations where the active field value on table leadsdetails is not 0, for the given ID, and showing only rows where that count is 0 (ie. for the given id the active field is ALWAYS 0)
select l.id, l.name
from lead l
join leadsdetails ld
on l.id = ld.lead_id
group by l.id, l.name
having sum(case when ld.active <> 0 then 1 else 0 end) = 0
Fiddle: http://www.sqlfiddle.com/#!2/00970/2/0
As you need to get the records only when active column doesn't have 1
use NOT EXISTS
SQL FIDDLE DEMO : http://www.sqlfiddle.com/#!2/00970/1
SELECT * FROM
Lead L
WHERE NOT EXISTS (
SELECT 1 FROM LeasdDetails LD
where L.id = LD.lead_id
AND LD.active =1
)
I think you can do what you want with an exists clause:
select l.*
from Lead l
where exists (select 1 from LeadsDetails ld where ld.lead_id = l.id and ld.active = 0)