Why wont the following work?
SELECT SUM(startUserThreads.newForStartUser)+SUM(endUserThreads.newForEndUser) AS numNew ...
It returns an empty string.
The following is returning 1 for my data set however:
SELECT SUM(startUserThreads.newForStartUser) AS numNew ...
How do I add the two sums correctly?
The whole thing:
SELECT t.*,
COUNT(startUserThreads.id) + COUNT(endUserThreads.id) AS numThreads,
SUM(startUserThreads.newForStartUser) + SUM(endUserThreads.newForEndUser) AS numNew
FROM `folder` `t`
LEFT OUTER JOIN `thread` `startUserThreads`
ON ( `startUserThreads`.`startUserFolder_id` = `t`.`id` )
LEFT OUTER JOIN `thread` `endUserThreads`
ON ( `endUserThreads`.`endUserFolder_id` = `t`.`id` )
WHERE user_id = :user
FYI, only two users can share a thread in my model. That should explain my column names
SELECT COALESCE(SUM(startUserThreads.newForStartUser),0)+COALESCE(SUM(endUserThreads.newForEndUser),0) AS numNew ...
From the MySQL docs
SUM([DISTINCT] expr)
Returns the sum of expr. If the return set has no rows, SUM() returns
NULL. The DISTINCT keyword can be used in MySQL 5.0 to sum only the
distinct values of expr.
SUM() returns NULL if there were no matching rows.
Aggregate (summary) functions such as COUNT(), MIN(), and SUM() ignore
NULL values. The exception to this is COUNT(*), which counts rows and
not individual column values.
Maybe try COALESCE( SUM(x), 0 ) + COALESCE( SUM(y), 0 )?
Related
So I found a bug in my application, it wasn't showing me a result it should have. I traced it back to the following SQL query (I removed the irrelevant parts).
As you can see the query selects rows from wc_hncat_products of which the corresponding id's have a count of >= 1 inside the wc_hncat_product_category_has_product table
If I execute the query with the subquery result as a column, you can see the result is 1. But when I use it in the WHERE clause the >= 1 comparison fails.
Proof that the subquery DOES return 1:
SELECT `wc_hncat_products`.`id`,
(SELECT Count(*)
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' )) count
FROM `wc_hncat_products`
WHERE `id` IN ( '785' )
This query returns one row, with the column count value being 1
No results with subquery count comparison in WHERE clause
SELECT `wc_hncat_products`.`id`
FROM `wc_hncat_products`
WHERE (SELECT Count(*)
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' )) >= 1
AND `id` IN ( '785' )
This query selects 0 rows..
How is this possible? You can see the count actually is 1, but the comparison still fails as no results are being returned while the subqueries are identical in both scenarios.
The standard way to implement that type of check is to use EXISTS.
Something like this should work for you:
SELECT `wc_hncat_products`.`id`
FROM `wc_hncat_products`
WHERE EXISTS (SELECT NULL
FROM `wc_hncat_product_categories`
INNER JOIN `wc_hncat_product_category_has_product`
ON `wc_hncat_product_categories`.`id` =
`wc_hncat_product_category_has_product`.`category_id`
WHERE `wc_hncat_product_category_has_product`.`product_id` =
`wc_hncat_products`.`id`
AND `category_id` IN ( '1' ))
AND `id` IN ( '785' )
I need to please change this SQL query to NOT use sub-query with IN, I need for this query to work faster.
here is the query i am working on. About 7 million rows.
SELECT `MovieID`, COUNT(*) AS `Count`
FROM `download`
WHERE `UserID` IN (
SELECT `UserID` FROM `download`
WHERE `MovieID` = 995
)
GROUP BY `MovieID`
ORDER BY `Count` DESC
Thanks
Something like this - but (in the event that you switch to an OUTER JOIN) make sure you're counting the right thing...
SELECT MovieID
, COUNT(*) ttl
FROM download x
JOIN download y
ON y.userid = x.userid
AND y.movieid = 995
GROUP
BY x.MovieID
ORDER
BY ttl DESC;
Use Exists instead, see Optimizing Subqueries with EXISTS Strategy:
Consider the following subquery comparison:
outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where) MySQL
evaluates queries “from outside to inside.” That is, it first obtains
the value of the outer expression outer_expr, and then runs the
subquery and captures the rows that it produces.
A very useful optimization is to “inform” the subquery that the only
rows of interest are those where the inner expression inner_expr is
equal to outer_expr. This is done by pushing down an appropriate
equality into the subquery's WHERE clause. That is, the comparison is
converted to this:
EXISTS (SELECT 1 FROM ... WHERE subquery_where AND
outer_expr=inner_expr) After the conversion, MySQL can use the
pushed-down equality to limit the number of rows that it must examine
when evaluating the subquery.
filter direct on movieId..you does not need to add sub query. it can be done by using movieID =995 in where clause.
SELECT `MovieID`, COUNT(*) AS `Count`
FROM `download`
WHERE `MovieID` = 995
GROUP BY `MovieID`
ORDER BY `Count` DESC
I have a query on a Left join, where the Table who joins can contain zero rows. The problem is that if I select from that, then there are no rows where the join table contains zero rows.
How can I select it then anyway?
Here is my query
SELECT server.id
, COALESCE( AVG( playerData.player ) , 0 ) AS average
FROM server
LEFT JOIN playerData ON server.id = playerData.serverID
AND (playerData.timestamp > UNIX_TIMESTAMP( ) -10000)
The playerData table stores in one row how many people were on a server on a specific time. And multiple rows of this needs to be calculated to an average and this needs to be joined to the other query. When I omit the secound select column it gives me all rows (like it should), otherwise it only shows a result where also appropriate rows in the playerData table exists.
Additional Table data: playerData Table:
For the other table only the id column is important in this case.
Try this:
SELECT server.id
, COALESCE( AVG( playerData.player ) , 0 ) AS average
FROM server
LEFT JOIN playerData ON server.id = playerData.serverID
AND (playerData.timestamp > UNIX_TIMESTAMP( ) -10000)
group by server.id
Your query is missing the group by clause. When you include an aggregation function (like AVG()), the query automatically becomes an aggregation query. Without group by, all rows are aggregated into a single row. Presumably, you want one row per server.id.
I ran into a really strange problem today when using the MySQL function GROUP_CONCAT:
I have the following query:
SELECT SUM(total) FROM order WHERE customer_id='X' AND order_status_id IN ((SELECT GROUP_CONCAT(order_status_id SEPARATOR ',') FROM order_status WHERE profit='1'))
but that returns NULLL, however:
SELECT SUM(total) FROM order WHERE customer_id='X' AND order_status_id IN (1,2,3,4,5,6,7,8)
this works as well as the first query to concat the status id's, grouped however they return NULL as total
GROUP_CONCAT() returns a string, which is a single value. The IN() clause, although it accepts a comma-separated list of values, won't take just any string you give it and then parse out the individual values.
It treats the result of the GROUP_CONCAT() as a single string unit, which could be a member of many other strings in a comma-separated list, but no rows match order_status_id = '1,3,5,6', which is what the RDBMS ultimately sees.
If you want to use a query for that IN() clause, use a subquery. The IN () clause knows how to deal with the rowset returned by the subquery and will treat it appropriately.
SELECT
SUM(total)
FROM order
WHERE
customer_id='X'
AND order_status_id IN (
SELECT order_status_id FROM order_status WHERE profit = '1'
);
About your question. Try to use FIND_IN_SET function -
SELECT
SUM(total)
FROM
`order`
WHERE
customer_id='X' AND
FIND_IN_SET(
order_status_id,
(SELECT GROUP_CONCAT(order_status_id) FROM order_status WHERE profit='1')
)
I'd suggest you to use JOIN clause. For example -
SELECT o.* FROM `order` o
JOIN order_status os
ON o.order_status_id = os.order_status_id
WHERE o.customer_id='X' AND os.profit = 1
...then add aggregate functions you need.
I have two tables in MySQL DB; table1, table2.
Both of them have a single column (float) values. It's actually a dump from our research project which produces a single value result.
And many of these values get repeated and sorting and filtering them in Python would be cumbersome, so I though perhaps dumping them in a table in DB would be quicker.
So the end result from the SQL query is the following grouped by the value:
value table1_count table2_count
1.0 0 1
1.1 1 3
2.1 4 5
The query I am coming up with is the following:
select everything.value, everything.count1, everything.count2
from
((
select X as value, count(*) from table1
) union all (
select X as value, count (*) from table2
)) everything
group by everything.value
into outfile "/count";
Any suggestions?
Thanks,
You can't do counts by group in the inner queries, since you're defining the groups in the outer query. This should be simpler:
select everything.value, count(*)
from
(
select X as value from table1
union all
select X from table2
) everything
group by value
into outfile "/count";
Also here's some trivia: when you use UNION, you need to define column aliases only in the first query unioned.
Re your comment. Here's one solution:
select everything.value, sum(t = 'success') as s, sum(t = 'failure') as f
from
(
select X as value, 'success' as t from table1
union all
select X, 'failure' from table2
) everything
group by value
into outfile "/count";
This uses a trick in MySQL that boolean expressions return 0 for false or 1 for true. So when you sum up a bunch of expressions, you get a count of the rows where the expression is true. (Don't rely on this trick in other brands of SQL database.)