Strange GROUP_CONCAT behaviour in MySQL - mysql

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.

Related

Sum all rows returning from SELECT statement

SELECT SUM(SELECT type.value
FROM type,item_type
WHERE item_type.type_id = type.id AND item_type.type_id IN (4,7)
GROUP BY type.id)
What's wrong with this query? I would like to sum all rows coming from the internal query.
You can't use SUM() function with subquerys. According to the manual the SUM() function returns the total sum of a numeric column. The way you were doing, was something like that: SELECT 1+50+30+10. Where is the table you were selecting the values? The sintax is:
SELECT SUM(column) FROM table
Take a look at:
http://www.w3schools.com/sql/sql_func_sum.asp
The correct way is
SELECT t.id, SUM(t.value)
FROM type as t,
INNER JOIN item_type as it
ON it.type_id = t.id
WHERE it.type_id IN (4,7)
GROUP BY t.id
Consider to use JOIN sintax instead of multiple tables: SQL left join vs multiple tables on FROM line?
You should learn to use proper join syntax and table aliases:
SELECT SUM(t.value)
FROM type t JOIN
item_type it
ON it.type_id = t.id
WHERE it.type_id IN (4,7);
If you want one row for each type.id, then you need a GROUP BY.
Your query doesn't work because subqueries are not allowed as arguments to aggregation functions. Even if they were, the context would be for a scalar subquery and your subquery is likely to return more than one row.
Just use SUM without internal query :
SELECT type.id, SUM(type.value)
FROM type,item_type
WHERE item_type.type_id = type.id AND item_type.type_id IN (4,7)
GROUP BY type.id

Using alias in sql to compute other value

I've this query. I want to perform addition on Total1 and Total2 which are aliases. My query is not working mysql is showing Unknown column error.
SELECT p.Quantity*p.Price AS Total1,
p.Quantity+p.Tax AS Total2,
p.Total1+p.Total2 AS Total
FROM p
ORDER BY id
You can't reuse aliases in your select clause
SELECT p.Quantity*p.Price AS Total1,
p.Quantity+p.Tax AS Total2,
p.Quantity*p.Price + p.Quantity+p.Tax AS Total
FROM p
ORDER BY id
Only in group, having, order clauses.
Aliases are evaluated at the very end during the lifecylce of a select statement. These are normally for output purposes only and are not usable for computation
The Sequence of a select statement Evaluation is:
1. From
2. Where
3. Order / grouping
4. Select ( fields and allias)

COUNT(*) returning multiple rows instead of just one

Why does COUNT() return multiple rows when I just need the total count of how many rows my query generates?
Should return 1078.
The COUNT() is working as expected. When you put a group by clause, the count() gives you the result for GROUP BY. If you wish to get the count of rows in a query that includes group by, use it as a subquery instead.
Something like:
SELECT COUNT(*) FROM (SELECT * FROM `table`
GROUP BY `column1`) AS `a`
Well, simple answer. Don't GROUP BY if you don't need groups.
Either use COUNT(DISTINCT articles.company) without GROUP BY or keep the the GROUP BY and wrap the whole query in a SELECT COUNT(*) FROM (...) AS data, if you want to count the groups.
Do not use group by, it will count the number of each group.
Write the above query as subquery then it will give proper result and dont use group by
select count(*) from (select articles.id from 'contract_prices' left join 'articles' on
(arcticles.id = contract_prices.article)
where 'contract_to' >= curdate()
)

MySql query for min and max with grouping

Input Table :
By considering the above table I want to list the start and end date grouped by order id for the given input status "b". Right now I am doing it with many sql queries and merging them together in java. But I would like to write it in single sql query in mysql. Can anyone help me to write this in single sql query.
Output :
Use this:
SELECT OrderId, MIN(createdDate) as MinDate, MAX(createdDate) as MaxDate
FROM tbl1
WHERE fromStatus = 'b' or inputStatus = 'b'
GROUP BY OrderId
I suspect you lack the WHERE clause in your query.
SELECT orderID,
MIN(createdDate) min_date,
MAX(createdDate) max_date
FROM tableName
WHERE 'b' IN (fromStatus, toStatus)
GROUP BY OrderID

How to add two SUMs

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 )?