I'm using PDO to handle my database and I have one table:
Table:
id sku category
1 XYZ Ballerinas
2 Ballerinas
3 Ballerinas
4 ABC Ballerinas
As you can see I have 4 rows that are in the same category Ballerinas, but two of them don't have an sku. How can I return those rows using a PDO query only if all Ballerinas have an sku?
Thank you! :D
One option to find matching categories is to aggregate by category and then assert the total count matches the count of sku values which are not empty string. If these two counts match, then retain that category.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT category
FROM yourTable
GROUP BY category
HAVING COUNT(*) = COUNT(CASE WHEN sku <> '' THEN 1 END)
) t2
ON t1.category = t2.category;
Demo
Or you can do it without a join:
SELECT *
FROM Table1 t1
WHERE NOT EXISTS (SELECT 1 FROM Table1 t2 WHERE t1.category = t2.category AND t2.sku IS NULL);
If you consider empty values ('') also as "not being a value" then the condition in the exists clause should be
where t2.category=t1.category and not t2.SKU>''
Related
the sql as follows come from mysql document. it is:
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
The document say It finds all rows in table t1 containing a value that occurs twice in a given column , and doesnot explain the sql.
t1 and t is the same table, so the
count(*) in subquery == select count(*) from t
, isn't it?
count(*) in subquery == select count(*) from t
is wrong. because in mysql you can't use it like that. so you have to run it like that to get result of same id having two rows.
if you want to get count of same occurrence,
SELECT id, name, count(*) AS all_count FROM t1 GROUP BY id HAVING all_count > 1 ORDER BY all_count DESC
And also you can get values as your query like this as well,
select * from t1 where id in ( select id from t1 group by id having count(*) > 1 )
The query contains a correlated subquery in WHERE clause:
SELECT COUNT(*) FROM t1 WHERE t1.id = t.id
It is called correlated because it is related to the main query via t.id. So, this subquery counts the number of records having an id value that is equal to the current id value of the record returned by the main query.
Thus, predicate
(SELECT COUNT(*) FROM t1 WHERE t1.id = t.id) = 2
evaluates to true for any row with an id value that occurs twice in the table.
SELECT * FROM t1 AS t
WHERE 2 = (SELECT COUNT(*) FROM t1 WHERE t1.id = t.id);
This query goes through each record in t1 and then in the subquery looks into t1 again to see if in this case id is found 2 times (and only 2 times). You can do the same for any other column in t1 (or any table for that matter).
When you would like to see all values that are multiple times in the table, change WHERE 2 = by WHERE 1 <. This will also give you the values that are 3 times, 4 times, etc. in the table.
{
SELECT id,count( * )
FROM
MyTable
group by id
having count( * )>1
}
with this code, you can see the rows which repet more than one,
and you can change this query by yourself
How about using GROUP BY and HAVING:
SELECT id, count(1) as Total FROM MyTable AS t1
GROUP BY t1.id
HAVING Total = 2
I have a database with 2 tables. table1 and table2.
Table1 contains a list of tests ( column 'name' ). And I want to count how many rows are missing in table2 ( this table has also a column 'name' ) according to the list of tests of table1.
So I just want to count the mismatch between table1.name and table2.name.
I tried several querys, but all didnt really work.
I tried to use the 'NOT IN' statement but it takes too much time. Like several minutes.
For example, the output should be :
COUNT(*) = 20
It means that 20 tests are missing ( or not done yet ) in table2.
I'm using MySQL, so I can't use EXCEPT or MINUS statement.
Thank you by advance.
Nordine
You can use not exists :
select count(*)
from table1 t1
where not exists (select 1 from table2 t2 where t2.name = t1.name);
If you have a duplicate name in table1 then you need count(distinct t1.name) instead.
Try the below query:
select count(case when bname is null then 1 end)
from
(
select a.name as aname, b.name as bname from
table1 a left join table2 b
on a.name=b.name)x
MINUS can be used in MySQL.
Ref:http://www.mysqltutorial.org/mysql-minus/
Try this:
SELECT name
FROM table1
MINUS
SELECT name
FROM table2
I've two tables,
table 1
userid filter
thiru 1
thiru 2
thiru 3
raja 1
raja 2
table 2
headline filter1 filter2
test 1 3
test2 1 2
If I want to select the users applicable for filters.
when i select test - thiru is applicable ( filter1 and filter2 ) matching
when i select test2 - thiru and raja are applicable ( filter1 and filter2 ) matching.
Basically the filters are with and condition.
Here is the query that i tried:
select userid
from table1
where filter in (select filter1
from table2
where headline = 'test')
and filter in (select filter2
from table2
where headline = 'test');
Please give me the query for this.
Thanks in advance.
You can get the desired results for your both filters by using following approach
select a.userid
from table1 a
left join table2 b on a.filter = b.filter1
left join table2 b1 on a.filter = b1.filter2
group by a.userid
having sum(b.headline = 'test')
and sum(b1.headline = 'test')
demo(test) , demo(test2)
Essentially you're looking to join the two tables together on the filter in table1 being either = to filter1 or = filter2, and you only want usernames that appear twice in the joined list. This is what the group by does => afte rthe tables are joined together, it groups up the number of times the username appears. Then the HAVING COUNT(*) > 1 excludes all usernames that only appear once (i.e. only matched one of the filter1 or filter2)
SELECT
userid
FROM
table1 t1
INNER JOIN
table2 t2
ON
t1.filter=t2.filter1 OR
t1.filter=t2.filter2
WHERE
t2.headline = 'test'
GROUP BY
userid
HAVING COUNT(*) > 1
Your own query was actually almost working, but it has a fatal flaw:
You wrote WHERE filter in (something) AND filter in (somethingelse). A number 1 is never = to 1 AND 3 at the same time, so there is no one row whose filter can be 1 AND 3 simultaneously.. There are DIFFERENT rows that can match this, but for that your query would need to be:
select userid from table1
where
filter in (select filter1 from table2 where headline = 'test') OR
filter in (select filter2 from table2 where headline = 'test')
I only changed the AND to OR.. This would return two rows for THIRU and one row for RAJA, so we would still need to group it up and count them:
select userid from table1
where
filter in (select filter1 from table2 where headline = 'test') OR
filter in (select filter2 from table2 where headline = 'test')
GROUP BY username HAVING COUNT(*)>1
Soo.. you were close, you just need to think about things as row by row
You can use the below structure to get the result
select a.userid
from table1 a
join table2 b on (a.filter = b.filter1 or a.filter = b.filter2)
where b.headline = 'test'
group by a.userid
Found a solution and here is what worked:
SELECT userid FROM table1
WHERE (filter IN (SELECT filter1 FROM table2 WHERE headline = 'test')
OR filter IN (SELECT filter2 FROM table2 WHERE headline = 'test'));
Adding a 'OR' between two queries worked.
I have a table in SQL that is a list of users checking in to a website. It looks much like this:
id | date | status
------------------
Status can be 0 for not checking in, 1 for checked in, 2 for covered, and 3 for absent.
I'm trying to build one single query that lists all rows with status = 0, but also has a COUNT on how many rows have status = 3 on each particular id.
Is this possible?
MySQL VERSION
just join a count that is joined by id.
SELECT t.*, COALESCE(t1.status_3_count, 0) as status_3_count
FROM yourtable t
LEFT JOIN
( SELECT id, SUM(status=3) as status_3_count
FROM yourtable
GROUP BY id
) t1 ON t1.id = t.id
WHERE t.status = 0
note: this is doing the boolean sum (aka count)..
the expression returns either true or false a 1 or a 0. so I sum those up to return the count of status = 3 for each id
SQL SERVER VERSION
SELECT id, SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) as status_3_count
FROM yourtable
GROUP BY id
or just use a WHERE status = 3 and a COUNT(id)
Try a dependent subquery:
SELECT t1.*,
( SELECT count(*)
FROM sometable t2
WHERE t2.id = t1.id
AND t2.status = 3
) As somecolumnname
FROM sometable t1
WHERE t1.status=0
You can use a join for this. Write one query that will get all rows with a status zero:
SELECT *
FROM myTable
WHERE status = 0;
Then, write a subquery to get counts for the status of 3 for each id, by grouping by id:
SELECT COUNT(*)
FROM myTable
WHERE status = 3
GROUP BY id;
Since you want all the rows from the first table (at least that's what I am picturing), you can use a LEFT JOIN with the second table like this:
SELECT m.id, m.status, IFNULL(t.numStatus3, 0)
FROM myTable m
LEFT JOIN (SELECT id, COUNT(*) AS numStatus3
FROM myTable
WHERE status = 3
GROUP BY id) t ON m.id = t.id
WHERE m.status = 0;
The above will only show the count for rows containing an id that has status 0. Hopefully this is what you are looking for. If it is not, please post some sample data and expected results and I will help you try to reach it. Here is an SQL Fiddle example.
Is it possible/economical to perform a SELF JOIN of a table (for this example, my table called myTable has two columns pk and fk), and return a record if there is only one resulting record? I am thinking of something like the following, however, only_one_row() is a fictional function that would need to be replaced with something real:
SELECT fk
FROM myTable as t1
INNER JOIN myTable AS t2 ON t2.fk=t1.fk
WHERE t1.pk=1
AND only_one_row();
For instance, if myTable(id,fk) had the following records, only one record is produced, and I which to select the record:
1 1
2 1
3 2
However, if myTable(id,fk) had the following records, two '1' records are produced, and the select should not return any rows:
1 1
2 1
3 2
4 1
I could use PHP to do so, but would rather just use SQL if feasible.
Use a HAVING clause that counts the results.
SELECT fk
FROM myTable as t1
INNER JOIN myTable AS t2 ON t2.fk=t1.fk
WHERE t1.pk=1
HAVING COUNT(*) = 1
How about this:
SELECT fk
FROM myTable as t1
INNER JOIN myTable AS t2 ON t2.fk=t1.fk
WHERE t1.pk=1
GROUP BY fk
HAVING COUNT(fk) = 1