I am making a MySQL query where I want to retrieve an ID but only if I find a match for it in all the rows which I specify in the query.
Table: view_layout_rows
ID owner rows
___________________
49 1 2
50 1 2
Table: view_layout_rows_columns
ID row columns
___________________
49 1 5
49 2 4
50 1 5
50 2 5
SELECT vlr.id
FROM view_layout_rows vlr
INNER JOIN view_layout_rows_columns vlrc
ON vlr.id = vlrc.id
WHERE vlr.rows = 2
AND (vlr.owner = 0 OR vlr.owner = 1)
AND all of the following conditions should be satisfied:
(vlrc.row = 1 AND vlrc.columns = 5)
(vlrc.row = 2 AND vlrc.columns = 5)
Only ID 50 should be returned. 49 should NOT be returned as it only satisfies the first of the final two clauses.
How might I go about this?
(Please note, I asked this question previously but my requirement was unclear. Second attempt.)
Thanks in advance for any suggestions.
Double join to the rescue! :-)
SELECT vlc.*
FROM view_layout_rows vlc
INNER JOIN view_layout_rows_columns vlrc1 ON vlrc1.id = vlc.id
INNER JOIN view_layout_rows_columns vlrc2 ON vlrc2.id = vlc.id
WHERE vlrc1.row = 1 AND vlrc1.columns = 5
AND vlrc2.row = 2 AND vlrc2.columns = 5
/* imported from original query */
AND vlr.rows = 2
AND (vlr.owner = 0 OR vlr.owner = 1);
Single access of each table:
select r.*
from view_layout_rows r
join (select id, count(*) rec_count
from view_layout_rows_columns
where row in (1,2) and
columns = 5
group by id
having count(*) = 2) c
on r.id = c.id
where r.rows = 2 and
r.owner in (0,1)
Related
I have two tables as below.
PermissionAccessEntities
peID | petID
-------------------
1 | 1
2 | 4
3 | 1
4 | 2
5 | 4
6 | 4
-------------------
PermissionAccessEntityGroups
pegID | peID | gID
-----------------------------
1 | 5 | 1
2 | 5 | 2
3 | 5 | 3
4 | 6 | 2
5 | 6 | 3
-----------------------------
Now I've a getOne doctrine query as below-
select pae.peID from PermissionAccessEntities pae
left join PermissionAccessEntityGroups paeg1 on pae.peID = paeg1.peID
left join PermissionAccessEntityGroups paeg2 on pae.peID = paeg2.peID
where petID = 4 and paeg1.gID = 2 and paeg2.gID = 3;
Which returns 5 & 6. But I want to get the result which has exact number of matching rows. In this case which is 6.
Is there any way to use JOIN to fetch the same resultset as above ?.
Help is much appreciated.
Where condition will not help you in this case. Because, you want to consider count of all the rows for further filtering. You will need to use Group By with conditional filtering using Having clause.
We can also simplify query to use only one join with the PermissionAccessEntityGroups table.
Count() function is used to count the number of rows in a group. We can also use Sum( conditional statements ) to count number of rows matching a condition. Conditional statement will return 1 for matching rows, and 0 for non-matching rows.
Try the following query instead:
SELECT pae.peID
FROM PermissionAccessEntities AS pae
LEFT JOIN PermissionAccessEntityGroups AS paeg
ON pae.peID = paeg.peID
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = SUM(paeg.gID IN (2,3))
DB Fiddle DEMO
Now, remember that Count(NULL) = 0; however COUNT(0) = COUNT(1) = 1. So, another way of writing this query using Count() function only is:
SELECT pae.peID
FROM PermissionAccessEntities AS pae
LEFT JOIN PermissionAccessEntityGroups AS paeg
ON pae.peID = paeg.peID
WHERE pae.petID = 4
GROUP BY pae.peID
HAVING COUNT(*) = COUNT(CASE WHEN paeg.gID IN (2,3) THEN 1 END)
DB Fiddle DEMO 2
You can achieve your desired result by first looking for entries which match (2,3) and then seeing if any of those also match one of the other values. Any which doesn't (paeg2.peID IS NULL) is an exact match:
SELECT DISTINCT(pae.peID)
FROM PermissionAccessEntities pae
JOIN PermissionAccessEntityGroups paeg1 ON paeg1.peID = pae.peID AND paeg1.gID IN (2,3)
LEFT JOIN PermissionAccessEntityGroups paeg2 ON paeg2.peID = pae.peID AND paeg2.gID NOT IN (2,3)
WHERE pae.petID = 4 AND paeg2.peID IS NULL
Demo on dbfiddle
SELECT pae.peID FROM PermissionAccessEntities pae
INNER JOIN PermissionAccessEntityGroups paeg1 ON pae.peID=paeg1.peID
WHERE pae.petID = 4 AND paeg1.peID NOT IN (SELECT DISTINCT peID FROM
PermissionAccessEntityGroups WHERE gID NOT IN (2,3));
I have a MySQL database and SQL query with subqueries.
I'm 100% sure that the table s_k_p has only one row where s_k_p.season_id = 2 and s_k_p.user_id = k_i.user_id.
Anyway, the problem is that LEFT JOIN s_k_p AS skp2 part returns 10 rows. As said, it should return only one row.
SELECT skp2.season_id AS invalid_status_id
FROM comp_i
INNER JOIN k_i ON k_i.ilmo_id = comp_i.id
LEFT JOIN s_k_p
ON s_k_p.user_id = k_i.user_id
AND s_k_p.season_id = 4
LEFT JOIN s_k_p AS skp2
ON skp2.user_id = k_i.user_id
AND EXISTS (
SELECT *
FROM s_k_p
WHERE s_k_p.season_id = 2
AND s_k_p.user_id = k_i.user_id
)
WHERE comp_i.comp_id = ?
ORDER BY k_i.id ASC
The table s_k_p has the following rows:
season_id | user_id
1 | 25
1 | 459
2 | 459
3 | 459
3 | 9999
4 | 459
4 | 758
The second row is the only one where s_k_p.season_id = 2 and s_k_p.user_id = k_i.user_id should be true.
your query probably is correct in returning 10 rows if there are 10 rows for the USER in the S_K_P table because THAT is the left-join.
You have your exist to a SECONDARY level to the same S_K_P table but INCLUDING the Season_ID = 2.
If what you care about is only if it exists for the same user, season 2, then change to
LEFT JOIN s_k_p AS skp2
ON skp2.user_id = k_i.user_id
AND skp2.season_id = 2
I am trying to apply a conditional condition inside ON clause of a LEFT JOIN. What I am trying to achieve is somewhat like this:
Pseudo Code
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND (some condition)
AND (
IF (s.type = 0 AND s.code = 'me')
ELSEIF (s.type = 1 AND s.code = 'my-group')
ELSEIF (s.type = 2)
)
I want the query to return the row, if it matches any one of the conditions (Edit: and if it matches one, should omit the rest for the same item).
Sample Data
Sales
item_no | type | code | price
1 0 me 10
1 1 my-group 12
1 2 14
2 1 my-group 20
2 2 22
3 2 30
4 0 not-me 40
I want the query to return
item_no | type | code | price
1 0 me 10
2 1 my-group 20
3 2 30
Edit: The sales is table is used to apply special prices for individual users, user groups, and/or all users.
if type = 0, code contains username. (for a single user)
if type = 1, code contains user-group. (for users in a group)
if type = 2, code contains empty-string (for all users).
Use the following SQL (assumed, the the table sales has a unique id field as usual in yii):
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND id = (
SELECT id FROM sales
WHERE item_no = i.sku
AND (type = 0 AND code = 'me' OR
type = 1 AND code = 'my-group' OR
type = 2)
ORDER BY type
LIMIT 1
)
Try following -
SELECT *,SUBSTRING_INDEX(GROUP_CONCAT(s.type ORDER BY s.type),','1) AS `type`, SUBSTRING_INDEX(GROUP_CONCAT(s.code ORDER BY s.type),','1) AS `code`,SUBSTRING_INDEX(GROUP_CONCAT(s.price ORDER BY s.type),','1) AS `price`
FROM item AS i
LEFT JOIN sales AS s
ON i.sku = s.item_no AND (SOME CONDITION)
GROUP BY i.sku
I have three tables. Config, capability, and config_capability which associates the first two.
A config can have more than one capability so config_capability could look like
id | config_id | capability_id
1 1 1
2 1 2
3 2 1
4 2 2
5 2 3
I want to find the configs that have only certain capabilities.
SELECT
config.name
FROM
config
JOIN
config_capability AS cc
ON
config.id = cc.config_id
JOIN
capability
ON
cc.capability_id = capability.id
WHERE
config.node_count <= 4
AND cc.capability_id IN (
SELECT id
FROM capability
WHERE capability.name = 'cap1'
OR capability.name = 'cap2')
GROUP BY config.name
HAVING COUNT(cc.config_id) = 2
This query gives me config 1 and config 2 but I only want to find configs with capabilities 1 and 2 not 3
You can rewrite your query as below no need to use extra subquery while you have that table in join
SELECT
c.name
FROM
config c
JOIN
config_capability AS cc
ON
c.id = cc.config_id
JOIN
capability ca
ON
cc.capability_id = ca.id
WHERE
config.node_count <= 4
GROUP BY c.name
HAVING sum(ca.name NOT IN('cap1','cap2')) = 0
Demo
You can try:
HAVING COUNT(cc.config_id) = 2 and max(cc.config_id)<3
In My application I want to display all my friends and no of cheque given and received
Table Transaction Table Friends
---------------------------- -----------------------------
id given_id rev_id amt id who_id whom_id who_name
----------------------------- -------------------------------
1 2 1 1k 1 1 2 sss
2 2 3 1k 2 3 2 fff
3. 3 2 2k 3 4 1 eee
4 1 2 2k 4 2 1 iii
----------------------------- ------------------------------
Result whom_id=2 name=iii -> Friends (sss,fff)
=> sss gives totally 1 cheque and
sss receives totally 1 cheque and
fff gives 1 cheque and
fff receives 1 cheque and
I tried This one..
SELECT
p.who_id,
p.who_name,
COUNT( r1.give_id ) ,
COUNT( r1.rec_id )
FROM
friends p
LEFT JOIN Transaction r1
ON p.who_id = r1.give_id OR p.who_id = r1.rec_id
WHERE
p.whom_id = 1
GROUP BY p.who_id
Please provide me the best way to do this....
You can do it like this
SELECT
f.who_name,
count(t.given_id) GivenTotal,
count(lt.rev_id) as RecievedTotal
from friends as f
left join transaction as t
on t.given_id = f.who_id
left join transaction as lt
on lt.rev_id = f.who_id
where f.whom_id = 2
group by t.given_id
Demo
Output
who_name | GivenTotal | RecievedTotal
----------------------------------
sss | 1 | 1
fff | 1 | 1
try this,
select
id,
count(given_id) as given,
count(rev_id) as reveive
from Friends
GROUP BY id;
and if you whant the difference between the two amounts try this
select
id,
count(given_id) as given,
count(rev_id) as reveive,
given-receive as diff
from Friends
GROUP BY id;
You can use HAVING with group by ,
instead
WHERE p.whom_id = 1
There are two ways to do this, both involve joining on the Transactions table twice.
You can use subqueries:
SELECT f.who_id,
f.who_name,
t1.TotalGiven,
t2.TotalRev
FROM friends f
LEFT JOIN
(
select count(t.given_id) TotalGiven, t.given_id
from Transactions t
group by t.given_id
) t1
ON f.who_id = t1.given_id
LEFT JOIN
(
select count(t.rev_id) TotalRev, t.rev_id
from Transactions t
group by t.rev_id
) t2
ON f.who_id = t2.rev_id
where f.whom_id = 2;
See SQL Fiddle with Demo.
Or you can just use a join with no subquery:
select f.who_id,
f.who_name,
count(t1.given_id) TotalGiven,
count(t2.rev_id) TotalRev
FROM friends f
LEFT JOIN Transactions t1
ON f.who_id = t1.given_id
LEFT JOIN Transactions t2
ON f.who_id = t2.rev_id
where f.whom_id = 2
group by f.who_id, f.who_name
See SQL Fiddle with Demo
Finally I got the answer,
SELECT
p.who_id, p.who_name, COUNT( r1.give_id ) , COUNT( r2.rec_id )
FROM
friends p
LEFT JOIN Transaction r1 ON p.who_id = r1.give_id
LEFT JOIN Transaction r2 on p.who_id = r2.rec_id
WHERE
p.whom_id = 1
GROUP BY p.who_id