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;
Related
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;
Tables
__________________ ________________________________
|______name________| |____________scores______________|
|___id___|__name___| |_id_|_user-id_|_name-id_|_score_|
| 1 | bob | | 1 | 3 | 1 | 5 |
| 2 | susan | | 2 | 1 | 3 | 4 |
| 3 | geoff | | 3 | 3 | 2 | 3 |
| 4 | larry | | 4 | 2 | 4 | 5 |
| 5 | peter | | 5 | 1 | 1 | 0 |
-------------------- ----------------------------------
Im looking to write a query that returns a RANDOM name from the 'name' table, that the user hasnt scored so far.
So given user '1' for example, it could return 'susan, larry or peter' as user '1' hasnt given them a score yet.
SELECT *
FROM names
LEFT JOIN
votes
ON names.id = votes.name_id
WHERE votes.user_id = 1
AND (votes.score IS NULL);
So far I have this, but it doesnt seem to be working as I would like
(atm it doesnt return a random, but all, but this is wrong)
Any help would be appreciated.
If you are filtering on some field of outer joined table type of join is automatically changed to inner. In your case it's condition
votes.user_id = 1
So you need to move that condition from WHERE to ON
SELECT *
FROM names
LEFT JOIN
votes
ON names.id = votes.name_id and votes.user_id = 1
WHERE (votes.score IS NULL);
Consider moving the condition from WHERE to JOIN ON clause since you are performing an OUTER JOIN else the effect would be same as INNER JOIN
LEFT JOIN votes
ON names.id = votes.name_id
AND votes.user_id = 1
WHERE votes.score IS NULL
ORDER BY RAND();
You could apply :
SELECT name FROM name join scores on name.id=scores.user_id WHERE scores.score=0
You can perform this as a sub-query
SELECT *
FROM names
WHERE id NOT IN (SELECT name_id FROM votes WHERE user_id=1)
ORDER BY RAND()
LIMIT 1
This is my scenario
I have a permissions table with the following fields.
id | module | permission
1 | client | add
2 | client | edit
3 | client | delete
4 | someth | edit
5 | someth | delete
employee table
id | status | somestatus
1 | act | 1
2 | den | 1
3 | act | 0
4 | den | 1
5 | act | 0
6 | act | 1
Now what i would need to do is select the employee who have status="act" and somestatus=1 and give them all permissions where module="client"
so the table employee_permissions should have these rows
id | empid | permid | permvalue
1 | 1 | 1 | 1
2 | 1 | 2 | 1
3 | 1 | 3 | 1
1 | 6 | 1 | 1
2 | 6 | 2 | 1
3 | 6 | 3 | 1
This is the query I tried and I'm stuck here
INSERT INTO at2_permission_employee (employee_id,permission_id)
SELECT at2_employee.employee_id as employee_id
, (SELECT at2_permission.permission_id as permission_id
FROM at2_permission
where at2_permission.permission_module='client'
)
from at2_employee
where at2_employee.employee_status='Active'
and at2_employee.employees_served_admin = 1;
I get the error sub query returns multiple rows which makes sense to me. But I'm not sure how to modify the query to account for iterating over the rows returned by sub query
If I'm not wrong, like this:
INSERT INTO at2_permission_employee (employee_id, permission_id, permvalue)
SELECT
at2_employee.employee_id,
at2_permission.permission_id,
1
FROM at2_permission cross join at2_employee
WHERE
at2_employee.employee_status='Active'
and at2_employee.employees_served_admin = 1
and at2_permission.permission_module='client';
It's a bit unclear where the value for permvalue should come from so I hard coded it and used the permission.id for both id and permid, but this query should give you an idea on how to accomplish what you want:
insert employee_permissions (id, empid, permid, permvalue)
select p.id, e.id, p.id, 1
from employee e, permissions p
where p.module = 'client' and e.status = 'act' and e.somestatus = 1;
I have a small problem I have a MySQL Table called categories that looks like so:
| id | parent_id | name | position | status | ... |
| 1 | 0 | A | 1 | 1 | ... |
| 2 | 1 | A1 | 2 | 1 | ... |
| 3 | 2 | A2 | 1 | 1 | ... |
| 4 | 1 | A3 | 1 | 1 | ... |
| 5 | 0 | B | 2 | 1 | ... |
Basically a table that holds all my categories with multi level depth, each category that is a sub category has a parent_id > 0. At any given time I am using the following SQL statement to only select the top level categories that have parent_id = 0 and their first level children that have parent_id = id of category with parent_id = 0.
SELECT * FROM categories WHERE parent_id = 0 UNION ALL SELECT c.* FROM categories c
INNER JOIN categories p ON c.parent_id = p.id WHERE p.parent_id
1. Problem
This will always select all categories even if they have status = 0 which is a problem. So I tried adding AND status = 1 to both WHERE statements however I this does not work as all categories get selected regardless of status.
Second thing I tried is since on first select I'm only selecting categories with parent_id = 0 and then making a UNION with all categories where parent_id matches id's of those from the first select I could just add AND status = 0 to only the first SELECT WHERE and then the parent category that has status 0 would not get selected and thus when UNION is made it's children would also not get selected. However if I just add AND status = 1 to the first WHERE then I only get the categories with parent_id & status = 1 and nothing happens in the UNION.
2. Problem
Once I do this select I would have to order the categories and subcategories by the position value this can be done in PHP using the sort functions but this is pretty expansive when you have some 8000 categories.
I tried adding ORDER BY id ASC, position ASC. After my last WHERE statement I would like it so that I would get an output like so:
| id | parent_id | position |
| 1 | 0 | 1 |
| 3 | 1 | 1 |
| 6 | 1 | 2 |
| 2 | 0 | 2 |
| 4 | 2 | 1 |
Or even:
| id | parent_id | position |
| 1 | 0 | 1 |
| 2 | 0 | 2 |
| 3 | 1 | 1 |
| 6 | 1 | 2 |
| 4 | 2 | 1 |
I thot that second example would be pretty trivial and I got it to work when my statement did not include UNION ALL. But with the UNION my statement just like with the status = 1 returns only parent categories.
SELECT * FROM categories WHERE parent_id = 0 UNION ALL SELECT c.* FROM categories c
INNER JOIN categories p ON c.parent_id = p.id WHERE p.parent_id ORDER BY parent_id ASC, position ASC;
Since all parents have parent_id = 0 they would be listed first however ordered by position and then all children would be ordered together by parent_id first and then by position.
If I have understood correctly, I think you want the following:
SELECT DISTINCT c.* FROM categories c, categories p
WHERE c.status<>0 and (c.parent_id = 0 OR (c.parent_id=p.id and p.parent_id=0))
ORDER BY c.id,c.position
Hello there I have a following table
------------------------------------------
| id | language | parentid | no_daughter |
------------------------------------------
| 1 | 1 | 0 | 2 |
------------------------------------------
| 1 | 1 | 0 | 2 |
------------------------------------------
| 2 | 1 | 1 | 1 |
------------------------------------------
| 2 | 2 | 1 | 1 |
------------------------------------------
| 3 | 1 | 1 | 0 |
------------------------------------------
| 3 | 2 | 1 | 0 |
------------------------------------------
| 4 | 1 | 2 | 0 |
------------------------------------------
| 4 | 2 | 2 | 0 |
------------------------------------------
| 5 | 1 | 2 | 0 |
------------------------------------------
| 5 | 2 | 2 | 1 |
-----------------------------------------
| 5 | 1 | 4 | 1 |
------------------------------------------
| 5 | 2 | 4 | 1 |
------------------------------------------
Scenario
Every record has more than one rows in table with different language ids. parentid tells who is the parent of this record. no_daughter columns tells against each record that how many child one record has. Means in Ideal scenario If no_daughter has value 2 of id = 1 , it means 1 should be parentid of 2 records in same table. But If a record has more than one exitance with respect to language, it will be considered as one record.
My Problem
I need to find out those records where no_daughter value is not correct. It means if no_daughter is 2, there must be two records whoes parentid has that id. In above case record with id = 1 is valid. But record having id = 2 is not valid because the no_daughter = 1 but actual daughter of this record is 2. Same is the case with id=4
Can any body tell me how can I find these faulty records?
Updated after answers
Ken Clark has and shola has given answer which return same result for example shola query is
SELECT DISTINCT
id
FROM
tbl_info t
INNER JOIN
(SELECT
parentid,
COUNT(DISTINCT id) AS childs
FROM
tbl_info
GROUP BY parentid) AS parentchildrelation
ON t.id = parentchildrelation.parentid
AND t.no_daughters != parentchildrelation.childs
This query is returning those ids who have been used as parentid somewhere in table but having wrong no_daughter values. But not returning ids that has value in no_daugter columns but have not been used as parentid any where in table. For exampl id = 5 has no_daughter = 1 but it is not used as parentid in table. So it is also a faulty record. But above query is not capturing such records.
Any help will be much appreciated.
Try this:
SELECT DISTINCT
id
FROM
tbl_info t
Left JOIN
(SELECT
parentid,
COUNT(DISTINCT id) AS childs
FROM
tbl_info
GROUP BY parentid) AS parentchildrelation
ON t.id = parentchildrelation.parentid
Where t.no_daughters != parentchildrelation.childs
Try this:
SELECT id FROM tinfo t inner join
(SELECT parentid, COUNT(distinct language ) as childs FROM tinfo group by parentid) as summary
on t.id=summary.parentid and t.no_daughters!= summary.childs
try this
Select Distinct * From tablename t
Left Join
(
Select COUNT(t1.Id) Doughter,t1.parentid,t1.language From tablename t1 Group By t1.parentid,t1.language
)tbl
On t.id=tbl.parentid And tbl.language=t.language And t.no_daughter<>tbl.Doughter