let me show table structure first then my question
suppose table A
id | url |
1 | page
2 | home
3 | product
4 | sell
and table b
id |user_id | table a id
1 | 1 | 1
the output which I want like
id | url | ispermission
1 | page | 1
2 | home | 0
3 | product | 0
4 | sell | 0
(value 1 )in ispermission mean that it map with user as you can see in table b other mean it does not have mapping
below is my query
select p.id,p.url,if(r.user_id=4,1,0) ispermission from
`table a` p
left join `table b` r on p.id=r.url_id
group by p.id,p.url order by ispermission DESC
this query is working great but in some case it got failed the result let conside that failed case the output which i m getting like (note this result is without groupby)
id | url | ispermission
1 | page | 0
1 | page | 1
2 | home | 0
3 | product | 0
4 | sell | 0
by using group by i m getting result like
id | url | ispermission
1 | page | 0
2 | home | 0
3 | product | 0
4 | sell | 0
Are you looking for something like this?
SELECT
T1.ID,
T1.Url,
COUNT(T2.[table a id]) Impression
FROM TableA T1
LEFT JOIN TableB T2 ON T1.ID = T2.[table a id]
GROUP BY T1.ID,T1.Url
Using LEFT JOIN with CASE expression:
select a.id, a.url,
case when b.tableAid is not null then 1 else 0 end as ispermission
from TableA a
left join TableB b on b.tableAid = a.id
Demo on db<>fiddle
Related
I have two tables. One with main data (messages) and second with stats (messages_open_history).
messages:
id | name
1 | m1
2 | m2
3 | m3
4 | m4
messages_open_history:
id | message_id | opened | date
1 | 1 | 0 | 2019-09-01
2 | 1 | 1 | 2019-09-02
3 | 2 | 0 | 2019-09-01
4 | 2 | 0 | 2019-09-02
5 | 2 | 0 | 2019-09-03
6 | 3 | 1 | 2019-09-01
7 | 3 | 0 | 2019-09-02
8 | 4 | 1 | 2019-09-01
I would like to check if any Message was opened.
id | name | opened
1 | m1 | 1
2 | m2 | 0
3 | m3 | 1
4 | m4 | 1
I have tried:
SELECT m.id, m.name, opened FROM messages m
LEFT JOIN messages_open_history moh
Use exists:
select m.*,
(exists (select 1
from messages_open_history moh
where moh.message_id = m.id and
moh.opened = 1
)
) as ever_opened
from messages m;
This can take advantage of an index on messages_open_history(message_id, opened).
One way is to solve this is using Max() aggregation on opened field with Group By. Now, it seems that opened field has only two values either 0 or 1.
So we can also use LEFT JOIN (with condition opened = 1) with DISTINCT. If the message has not been opened at all, LEFT JOIN will result in NULL. We can then use Coalesce() to consider it as 0.
SELECT DISTINCT m.id, m.name, COALESCE(moh.opened, 0) AS opened
FROM messages AS m
LEFT JOIN messages_open_history AS moh
ON moh.message_id = m.id
AND moh.opened = 1
ORDER BY m.id
Result
| id | name | opened |
| --- | ---- | ------ |
| 1 | m1 | 1 |
| 2 | m2 | 0 |
| 3 | m3 | 1 |
| 4 | m4 | 1 |
View on DB Fiddle
For good performance, please define the following composite index: (message_id, opened) on the messages_open_history table.
If you are using MySQL v 8.0 or higher, another way to get the correct result is by using window function-
SELECT id, name, opened
FROM (SELECT m.id, m.name, moh.opened
,row_number() over(partition by m.name order by moh.opened desc) is_open
FROM messages AS m
JOIN messages_open_history AS moh ON moh.message_id = m.id) open_msg
WHERE is_open = 1
I hope this works for you:
select t1.id, t1.name, max(t2.opened)
from messages t1
join messages_open_history t2 on t1.id = t2.message_id
group by t1.id, t1.name
I was given a SQL assignment that is the following table simulating a dating app: Table name = dating
user_id | viewing_profile_id | date | liked
1 2 x yes
1 3 x yes
2 1 x yes
2 3 x no
3 1 x no
3 2 x no
essentially I want to see the % of profiles that match each other. a match is when both profiles like each other.
I think I know what I have to do. Perform a Self join onto the table itself and use a case when for when the profiles like each other.
select t.date, sum(t.match) / count(t.match) as p_match
from (
select s1.user_id, s1.viewing_profile_id,
date_trunc('day',s1.date) as date, case when s1.liked = 'yes'
and s2.liked = 'yes' then 1 else 0 end as match
from dating s1
left join dating s2 on s2.ser_id = s1.viewing_profile_id
group by 1,2) t
group by 1
Since this is just a made up table, and I do not have any data execute this on, I was wondering if I can get some insight into whether or not this would work.
I am expecting the subquery to produce something like the following:
user_id | viewing_profile_id | date | match
1 2 x 1
1 3 x 0
2 1 x 1
2 3 x 0
3 1 x 0
3 2 x 0
You need to left self join the table on the conditions you have:
select
d1.*,
case when d2.user_id is null then 0 else 1 end `match`
from dating d1 left join dating d2
on
d1.user_id = d2.viewing_profile_id
and d1.viewing_profile_id = d2.user_id
and d1.liked = 'yes' and d2.liked = 'yes'
order by d1.user_id, d1.viewing_profile_id
See the demo.
Results:
| user_id | viewing_profile_id | date | liked | match |
| ------- | ------------------ | ---- | ----- | ----- |
| 1 | 2 | | yes | 1 |
| 1 | 3 | | yes | 0 |
| 2 | 1 | | yes | 1 |
| 2 | 3 | | no | 0 |
| 3 | 1 | | no | 0 |
| 3 | 2 | | no | 0 |
/* for matched users*/
SELECT *
FROM user viewed, user viewing
WHERE viewed.user_id = viewing.viewing_profile_id
and viewed.liked='yes'
and viewing.liked='yes'
/* for Match_Percentage */
SELECT
(SELECT count(*)
FROM user viewed, user viewing
WHERE viewed.user_id = viewing.viewing_profile_id
and viewed.liked='yes'
and viewing.liked='yes')
/
(SELECT count(*) FROM user)
*100 as Match_Percentage
FROM dual;
If you just want a flag specifying whether the reverse matches, then:
select d.*,
(exists (select 1
from dating d2
where d2.user_id = d.viewing_profile_id and
d2.viewing_profile_id = d.user_id and
d2.liked = 'yes'
) and
d.liked = 'yes'
) as match
from dating d;
Need help in Building a Query which can select a Item and sum up its QTY which is in 2 different Tables.
Example Scenario:
Table 1:
ID | ITEM_NAME | QTY |
1 | Item_Desc1 | 0 |
2 | Item_Desc2 | 2 |
3 | Item_Desc3 | 4 |
4 | Item_Desc4 | 0 |
Table 2:
ID | ITEM_ID | BATCHNO | QTY
1 | 1 | B1 | 100
2 | 1 | B2 | 100
3 | 2 | B3 | 0
4 | 3 | B2 | 100
5 | 4 | B2 | 200
6 | 4 | B3 | 100
Need a Query to show in a Data grid Table as follows:
ID | Item_Name | QTY
1 | Item_Desc1 | 200
2 | Item_Desc2 | 2
3 | Item_Desc3 | 104
4 | Item_Desc4 | 300
Note:
This Query should be useful to run a Search query using 'LIKE' operator by using which User can search for Items Needed
SAMPLE Image of My APPLICATION to Run Search query using Table 1 and Table 2
SAMPLE Image of My APPLICATION DATABASE - TABLE2
SAMPLE Image of My APPLICATION DATABASE - TABLE1
To get sum from 2 table you can use following query
select a.ID, a.ITEM_NAME, a.QTY + coalesce(b.QTY,0)
from Table1 a
left join (
select ITEM_ID,sum(QTY) QTY
from Table2
group by ITEM_ID
) b on a.ID = b.ITEM_ID
Demo
Try the following query
select tbl1.id as ID,tbl1.Item_Name, tbl.qty+sum(tbl2.qty) as QTY
from table1 as tbl1 JOIN table2 as tbl2
ON tbl1.id = tbl2.id group by tbl2.item_id
I need to query data from multiple tables, below are the major tables(simplified).
Project
+-----+-------+-------+
| pid | pname | status| //status: 0 = pending, 1 = complete
+-----+-------+-------+
| 1 | Proj1 | 0 |
| 2 | Proj2 | 1 |
| 3 | Proj3 | 0 |
+-----+-------+-------+
Module
+-----+--------+-------+----------+-----------------+
| mid | pid | status| priority |modulecategoryid |
+-----+--------+-------+----------+-----------------+
| 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 0 | 2 | 3 |
| 3 | 3 | 1 | 1 | 1 |
| 4 | 3 | 0 | 2 | 3 |
| 5 | 3 | 0 | 3 | 5 |
+-----+--------+-------+----------+-----------------+
Task
+----+--------+-------+----------+-----------------+
| id | mid | status| priority | taskcategoryid |
+----+--------+-------+----------+-----------------+
| 1 | 2 | 1 | 2 | 2 |
| 2 | 2 | 0 | 1 | 1 |
| 3 | 4 | 1 | 1 | 2 |
| 4 | 4 | 1 | 2 | 3 |
| 5 | 4 | 0 | 3 | 4 |
| 6 | 5 | 0 | 1 | 1 |
+----+--------+-------+----------+-----------------+
I am trying to get the pending tasks for all the pending projects that can be started first based on the module priority and task priority. i.e. for Proj3, module with priority 1 is completed so i should get first priority pending task for module 2.
I need to get the most prior task for each pending project with modulecategoryid and taskcategoryid for get its related info like this
+-----+--------+-----+------------------+----------------+
| pid | mid | tid | modulecategoryid | taskcategoryid |
+-----+--------+-----+------------------+----------------+
| 1 | 2 | 2 | 3 | 2 |
| 2 | 4 | 5 | 3 | 4 |
+----+---------+-----+------------------+----------------+
I am new to MySql and I have tried query with multiple joins and group it by projectids and min(priority) to get desired result. But columns that are not in group by are fetched randomly from the aggregate.
I have seen this answer SQL Select only rows with Max Value on a Column but that solves the problem for data in only one table.
Shall I get some help on that?
I can post my query if needed but it is getting wrong data.
SQL Select only rows with Max Value on a Column has the right approach. You just need to do it twice.
First create a subquery a showing the highest priority task for each module.
Then create a subquery b showing the highest priority Module for each project.
Then join your three tables and two subqueries together.
Here's a. It shows the highest priority Task id for each Module mid. (http://sqlfiddle.com/#!9/7eb1f3/4/0)
SELECT Task.id, Task.mid
FROM Task
JOIN (
SELECT MAX(priority) priority,
mid
FROM Task
WHERE status = 0
GROUP BY mid
) q ON q.priority = Task.priority AND q.mid = Task.mid
Here's b. It works the same way as a and shows the highest priority Module mid for each Project pid. (http://sqlfiddle.com/#!9/7eb1f3/3/0)
SELECT Module.mid, Module.pid
FROM Module
JOIN (
SELECT MAX(priority) priority,
pid
FROM Module
WHERE status = 0
GROUP BY pid
) q ON q.priority = Module.priority AND q.pid = Module.pid
Then you need a big JOIN to pull everything together. In outline it looks like this.
SELECT Project.pid, Project.pname,
Module.mid, Task.id tid,
Module.modulecategoryid, Task.taskcategoryid
FROM Project
JOIN ( /* the subquery called b */
) b ON Project.pid = b.pid
JOIN Module ON b.mid = Module.mid
JOIN ( /* the subquery called a */
) a ON Module.mid = a.mid
JOIN Task ON a.id = Task.id
WHERE Task.status = 0
The actual query looks like this, with the subqueries put in. (http://sqlfiddle.com/#!9/7eb1f3/2/0)
SELECT Project.pid, Project.pname,
Module.mid, Task.id tid,
Module.modulecategoryid, Task.taskcategoryid
FROM Project
JOIN (
SELECT Module.mid, Module.pid
FROM Module
JOIN (
SELECT MAX(priority) priority, pid
FROM Module
WHERE status = 0
GROUP BY pid
) q ON q.priority = Module.priority
AND q.pid = Module.pid
) b ON Project.pid = b.pid
JOIN Module ON b.mid = Module.mid
JOIN (
SELECT Task.id, Task.mid
FROM Task
JOIN (
SELECT MAX(priority) priority, mid
FROM Task
WHERE status = 0
GROUP BY mid
) q ON q.priority = Task.priority
AND q.mid = Task.mid
) a ON Module.mid = a.mid
JOIN Task ON a.id = Task.id
WHERE Task.status = 0
The secret to this is understanding that subqueries are virtual tables that you can join to each other or to ordinary tables. The skill you need is sorting out the combination of physical and virtual tables you need, and the join sequence.
Its very hard for to set a proper title, because I dont know how I describe my problem.
I have a table like this:
dlID | dl_seID | dlEpisode | dlFlag
___________________________________
1 | 1 | 1 | 0
2 | 1 | 2 | 1
3 | 1 | 3 | 1
4 | 2 | 1 | 1
5 | 2 | 2 | 0
6 | 3 | 1 | 0
What i want is a select query where I get something like this:
dlID | dl_seID | dlEpisode | dlFlag | dlFlagCount
_________________________________________________
1 | 1 | 1 | 0 | 2
2 | 1 | 2 | 1 | 2
3 | 1 | 3 | 1 | 2
4 | 2 | 1 | 1 | 1
5 | 2 | 2 | 0 | 1
6 | 3 | 1 | 0 | 0
dlFlagCount shoud be a counter of dlFlag = 1 where dl_seID = dl_seID.
Second try:
I need a value where I see how many Flags have the value 1 with the same dl_seID.
Is that possible?
I hope you guys know what I want^^
Regards
Try this:
select
a.*,
ifnull(b.ctflags,0)
from
tablea a left join
( select dl_seID, count(dlFlag) ctflags
from tablea
where dlFlag=1
group by dl_seID ) b on (a.dl_seID = b.dl_seID)
The left join is just to get the registry with 0 flags
See the fiddle: http://sqlfiddle.com/#!2/ef9b0/5
EDIT:
As op requested some explanation, here it goes:
What you asked is to count the amount of flags by the dl_seID and to do that you need to do this you separeta your problems, first you get the count for the dl_seID by flags, this is this subquery:
select dl_seID, count(dlFlag) ctflags
from tablea
where dlFlag=1
group by dl_seID
This became a 'separe table' or a new group of data, whatever you wanna call it. Then you have to join this with your original data (from your table) like the query for answer.
The left join part is because maybe there are some data that wont complain with where dlFlag=1 therefore if you want to get then as 0 you have to bring all values from table that exists or not on our created subgroup. And this ifnull(b.ctflags,0) is for theese data data exists on your table but has no flags (for your problem). If you use just b.ctflags it will bring null.
SELECT x.*
, COALESCE(y.flagcount,0) flagcount
FROM my_table x
LEFT
JOIN
( SELECT seID
, COUNT(*) flagcount
FROM my_table
WHERE flag = 1
GROUP
BY seid
) y
ON y.seid = x.seid;