How to check if a table contains a specific number of rows? - mysql

I have this query:
SELECT (COUNT(*) = SUM(status in (3, 5)) ) AS result
FROM `match` WHERE round_id = 15
this essentially check if the table match have all the items with a status 3 or 5 for the round 15. This works, but I actually want add another condition, in particular if the result is true I want check that all the records of that table with round_id = 15 are 20. How can I perform this?

Is this what you want?
SELECT (COUNT(*) = SUM(status in (3, 5)) AND COUNT(*) = 20) AS result
FROM `match`
WHERE round_id = 15;
This checks that there are 20 rows that match the conditions.

Related

SQL - Different conditions on the same column

I'm trying to achieve something very similar to SQL - Multiple conditions where clause the same column
The difference is that I want two separate WHERE conditions:
WHERE tag_id IN (1,2)
OR tag_id IN (3,2)
GROUP BY other_id HAVING COUNT(tag_id) = 2
This gives me all the records that I need, but also gives me records that have the tags 1 or 3 even when that record doesn't have tag_id = 2. I know that my problem is in the OR condition, because if I do (1,2) and (3,2) separately, I get the expected results for each query.
What am I missing?
You could use:
SELECT other_id
FROM yourTable
GROUP BY other_id
HAVING COUNT(tag_id) = 2 AND -- 2 tags
(SUM(tag_id NOT IN (1, 2)) = 0 OR -- either (1, 2)
SUM(tag_id NOT IN (3, 2)) = 0); -- or (3, 2)

Mysql select random from two tables where one column must contain two specific values [duplicate]

Lets consider the following table-
ID Score
1 95
2 100
3 88
4 100
5 73
I am a total SQL noob but how do I return the Scores featuring both IDs 2 and 4?
So it should return 100 since its featured in both ID 2 and 4
This is an example of a "sets-within-sets" query. I recommend aggregation with the having clause, because it is the most flexible approach.
select score
from t
group by score
having sum(id = 2) > 0 and -- has id = 2
sum(id = 4) > 0 -- has id = 4
What this is doing is aggregating by score. Then the first part of the having clause (sum(id = 2)) is counting up how many "2"s there are per score. The second is counting up how many "4"s. Only scores that have at a "2" and "4" are returned.
SELECT score
FROM t
WHERE id in (2, 4)
HAVING COUNT(*) = 2 /* replace this with the number of IDs */
This selects the rows with ID 2 and 4. The HAVING clause then ensures that we found both rows; if either is missing, the count will be less than 2.
This assumes that id is a unique column.
select Score
from tbl a
where a.ID = 2 -- based off Score with ID = 2
--include Score only if it exists with ID 6 also
and exists (
select 1
from tbl b
where b.Score = a.Score and b.ID = 6
)
-- optional? ignore Score that exists with other ids as well
and not exists (
select 1
from tbl c
where c.Score = a.Score and c.ID not in (2, 6)
)

Calculate count records from mysql group by fields

My table in MySQL
http://joxi.ru/5mdWRV8tyQzyr1
My programm pass array users
$ids = [1, 3, 7];
My query for table:
SELECT responsible_id, count(id) as count
from test
WHERE active = 1
AND status = 3
AND responsible_id in (1, 3, 7)
GROUP BY responsible_id
ORDER BY count(id)
I get result http://joxi.ru/vAWYGq0IMxdjmW
But, I need also first row with responsible_id = 7 and count = 0 if not exist on table.
To do what you want, use a left join:
SELECT v.responsible_id, count(t.id) as count
FROM (SELECT 1 as responsible_id UNION ALL
SELECT 3 as responsible_id UNION ALL
SELECT 7 as responsible_id
) v LEFT JOIN
test t
ON t.responsible_id = v.responsible_id AND
t.active = 1 AND
t.status = 3
GROUP BY v.responsible_id
ORDER BY count(id);
Note that the conditions in the WHERE have been moved to the ON clause.

Difference in columns. Returning variable top duplicate results

I have a query that returns the biggest difference in two columns. Lets say it's something like:
| result |
5
5
5
4
4
3
2
How can I make it return all of the top results every time? (5, 5, 5)
I'm not looking for LIMIT 3, since the results vary and sometimes there's only one top number, etc.
The query I have now looks like this:
SELECT MAX(column1 - column2) as result
FROM table
WHERE othercolumn = somecondition
GROUP by id
ORDER BY results asc
SELECT MAX(column1 - column2) as result
FROM table
WHERE othercolumn = somecondition
GROUP by id
HAVING result =
(select max(column1 - column2) FROM table WHERE othercolumn = somecondition)
ORDER BY id;
Not tested but it might work
select *,column1-column2 as result from table where column1 - column2 =
(SELECT (column1 - column2) as G
FROM table
ORDER BY G DESC limit 1)

use mysql SUM() in a WHERE clause

suppose I have this table
id | cash
1 200
2 301
3 101
4 700
and I want to return the first row in which the sum of all the previous cash is greater than a certain value:
So for instance, if I want to return the first row in which the sum of all the previous cash is greater than 500, is should return to row 3
How do I do this using mysql statement?
using WHERE SUM(cash) > 500
doesn't work
You can only use aggregates for comparison in the HAVING clause:
GROUP BY ...
HAVING SUM(cash) > 500
The HAVING clause requires you to define a GROUP BY clause.
To get the first row where the sum of all the previous cash is greater than a certain value, use:
SELECT y.id, y.cash
FROM (SELECT t.id,
t.cash,
(SELECT SUM(x.cash)
FROM TABLE x
WHERE x.id <= t.id) AS running_total
FROM TABLE t
ORDER BY t.id) y
WHERE y.running_total > 500
ORDER BY y.id
LIMIT 1
Because the aggregate function occurs in a subquery, the column alias for it can be referenced in the WHERE clause.
Not tested, but I think this will be close?
SELECT m1.id
FROM mytable m1
INNER JOIN mytable m2 ON m1.id < m2.id
GROUP BY m1.id
HAVING SUM(m1.cash) > 500
ORDER BY m1.id
LIMIT 1,2
The idea is to SUM up all the previous rows, get only the ones where the sum of the previous rows is > 500, then skip one and return the next one.
In general, a condition in the WHERE clause of an SQL query can reference only a single row. The context of a WHERE clause is evaluated before any order has been defined by an ORDER BY clause, and there is no implicit order to an RDBMS table.
You can use a derived table to join each row to the group of rows with a lesser id value, and produce the sum of each sum group. Then test where the sum meets your criterion.
CREATE TABLE MyTable ( id INT PRIMARY KEY, cash INT );
INSERT INTO MyTable (id, cash) VALUES
(1, 200), (2, 301), (3, 101), (4, 700);
SELECT s.*
FROM (
SELECT t.id, SUM(prev.cash) AS cash_sum
FROM MyTable t JOIN MyTable prev ON (t.id > prev.id)
GROUP BY t.id) AS s
WHERE s.cash_sum >= 500
ORDER BY s.id
LIMIT 1;
Output:
+----+----------+
| id | cash_sum |
+----+----------+
| 3 | 501 |
+----+----------+
When using aggregate functions to filter, you must use a HAVING statement.
SELECT *
FROM tblMoney
HAVING Sum(CASH) > 500