MySQL GROUP BY ignore or skip other null column - mysql

I have a table:
(id, storage_id, product_id, quantity, property_storage_group_id)
And I need min quantity, but when prouct_id is several, I need to ignore product_id with property_storage_group_id = null.
Something like this:
SELECT MIN(quantity), product_id
FROM storage_quantity
WHERE storage_id = 6
GROUP BY product_id
but without id 22, and with id 27.

You can use a subqueries. Try this:
SELECT MIN(s1.quantity), s1.product_id
FROM storage_quantity s1
WHERE s1.id NOT IN (SELECT s2.id
FROM storage_quantity s2
WHERE s2.product_id = s1.product_id
AND s2.storage_id = s1.storage_id
AND s2.property_storage_group_id IS NULL
AND (SELECT COUNT(s3.property_storage_group_id)
FROM storage_quantity s3
WHERE s3.product_id = s2.product_id
AND s3.storage_id = s2.storage_id
) > 0
)
WHERE s1.storage_id = 6
GROUP BY s1.product_id
The second subquery utilizes the fact that the COUNT() function automatically ignore NULL values, so it only returns the count of property_storage_group_id that are not NULL. If that count is greater than zero, then the first subquery selects all records with property_storage_group_id IS NULL for that product_id. Finally the main query excludes those records returned by the second query.

Related

Selecting distinct count in a group with only null values for a specific column

I have 2 columns like this - id and val.
I require such distinct id's where corresponding to each id there is a null value present.
Is it plausible to use "group by" by id and then use "having" clause where null is there?
I would use NOT EXISTS :
SELECT COUNT(DISTINCT id)
FROM table t
WHERE NOT EXISTS (SELECT 1 FROM table t1 WHERE t1.id = t.id AND t1.val IS NOT NULL);
Other option uses the GROUP BY :
SELECT COUNT(id)
FROM table t
GROUP BY id
HAVING SUM(CASE WHEN val IS NOT NULL THEN 1 ELSE 0 END) = 0;
To get ids that have a NULL value, I would be inclined to start with this:
select id
from t
group by id
having count(*) <> count(val);
This structure allows you to check for other values, such as a non-NULL value.
The simplest method to get the distinct ids with NULL values is:
select distinct id
from t
where val is null;
If you only want the count:
select count(distinct id)
from t
where val is null;

MySQL SUM returns no rows should return 0

There are no rows for this product_id. Result returns no rows instead of SUM = 0.
SELECT COALESCE(SUM(amount), 0) FROM store2product WHERE product_id = 6706434 GROUP BY product_id;
Is there a way to get result = 0?
There is no record for product_id = 6706434 in table store2product. As you group by product_id, you get one result row per product_id found with this query. As the product_id is not found, no row is returned.
Simple solution: remove GROUP BY.
SELECT
COALESCE(SUM(amount), 0)
FROM store2product
WHERE product_id = 6706434;
Now you get one result row in any case.
Try this Trick..
Schema for your case
CREATE TABLE #TAB (ID INT, AMT DECIMAL(18,2))
INSERT INTO #TAB
SELECT 1,1200
UNION ALL
SELECT 1,120
UNION ALL
SELECT 3, 100
Now query the table like
SELECT SUM(ISNULL(AMT,0)) AS AMT FROM (
SELECT ID, SUM(AMT)AMT FROM #TAB WHERE ID =2 GROUP BY ID
UNION ALL
SELECT NULL AS ID, NULL AS AMT
)A

MYSQL - Group By / Order By not working

I have the following data inside a table:
id person_id item_id price
1 1 1 10
2 1 1 20
3 1 3 50
Now what I want to do is group by the item ID, select the id that has the highest value and take the price.
E.g. the sum would be: (20 + 50) and ignore the 10.
I am using the following:
SELECT SUM(`price`)
FROM
(SELECT id, person_id, item_id, price
FROM `table` tbl
INNER JOIN person p USING (person_id)
WHERE p.person_id = 1
ORDER BY id DESC) x
GROUP BY item_id
However, this query is still adding (10 + 20 + 50), which is obviously not what I need to have.
Any ideas to where I am going wrong?
Here is what you are trying to achieve. First you need grouping in a subquery and not in outer query. In outer query you need only sum:
SELECT SUM(`price`)
FROM
(SELECT MAX(price) as price
FROM `table` tbl
INNER JOIN person p USING (person_id)
WHERE p.person_id = 1
GROUP BY item_id) x
http://sqlfiddle.com/#!9/40803/5
SELECT SUM(t1.price)
FROM tbl t1
LEFT JOIN tbl t2
ON t1.person_id= t2.person_id
AND t1.item_id = t2.item_id
AND t1.id<t2.id
WHERE t1.person_id = 1
AND t2.id IS NULL;
I'm not sure if this is the only requirement you have. If so, try this.
SELECT SUM(price)
FROM
(SELECT MAX(price)
FROM table
WHERE person_id = 1
GROUP BY item_id)
First of all - you don't need the person table, because the other table already contains the person_id. So i removed it from the examples.
Your query returns a sum of prices for each item.
If you replace SELECT SUM(price) with SELECT item_id, SUM(price) you wil get
item_id SUM(`price`)
1 30
3 50
But that is not what you want. Neither is it what you wrote in the question " (10 + 20 + 50)".
Now replacing the first line with SELECT id, item_id, SUM(price) you will get one row for each item with the highest id.
id item_id price
2 1 20
3 3 50
This works because of the "undocumented feature" of MySQL, wich allows you to select columns that are not listed in the GROUP BY clause and get the first row from the subselect each group (each item in this case).
Now you only need to sum the price column in an additional outer select
SELECT SUM(price)
FROM (
SELECT id, item_id ,price
FROM (
SELECT id, person_id, item_id, price
FROM `table` tbl
WHERE tbl.person_id = 1
ORDER BY id DESC ) x
GROUP BY item_id
) y
However i do not recomend to use that "feature". While it still works on MySQL 5.6, you never know if that will work with newer versions. It already doesn't work on MariaDB.
Instead you can determite the MAX(id) for each item in an subselect, select only the rows with the determined ids and get the summed price of them.
SELECT SUM(`price`)
FROM `table` tbl
WHERE tbl.id IN (
SELECT MAX(tbl2.id)
FROM `table` tbl2
WHERE tbl2.person_id = 1
GROUP BY tbl2.item_id
)
Another solution (wich internaly does the same) is
SELECT SUM(`price`)
FROM `table` tbl
JOIN (
SELECT MAX(tbl2.id) as id
FROM `table` tbl2
WHERE tbl2.person_id = 1
GROUP BY tbl2.item_id
) x ON x.id = tbl.id
Alex's solution also works fine, if the groups (number of rows per person and item) are rather small.
You have used group by in main query, but it is on subquery like
SELECT id, person_id, item_id, SUM(`price`) FROM ( SELECT MAX(price) FROM `table` tbl WHERE p.person_id = 1 GROUP BY item_id ) AS x

Replace null with value in mysql query with 0

I am trying replace null with 0 with following statement but returns no recrods instead of of catid supplied and 0.
select ifnull(count(*),0) as days, catid from mytable where Id=48 and catId=7
group by mytable.catId;
As far as I know, COUNT(*) does never return NULL. It returns 0 if there is no record.
count(*) never returns NULL, so you don't need any conditional logic:
select count(*) as days, catid
from mytable
where Id = 48 and catId = 7
group by mytable.catId;
Perhaps your issue is that the query is returning no rows. If so, you can leave out the group by. Then the query will always return one row:
select count(*) as days, catid
from mytable
where Id = 48 and catId = 7 ;

How to write a SQL query?

My database has a simple table, with two columns, BID and Value. There may be some records in the database with same BID, like this:
BID Value
Record1: BID = 1, Value = 0
Record2: BID = 1, Value = 3
Record3: BID = 2, Value = 4
Record4: BID = 2, Value = 5
Record5: BID = 2, Value = 6
Record6: BID = 3, Value = 7
Now I want to write a SQL query that can get the total count of the BID that has more than one corresponding records.
In the above sample, BID 1 has 2 corresponding records, and BID 2 has 3. So the total count of BID values that has more than one corresponding records is 2.
How to write such a SQL query?
You are looking for an aggregation query.
SELECT COUNT(*)
FROM (
SELECT BID, COUNT(*) cnt
FROM your_table
GROUP BY BID
HAVING COUNT(*) > 1
) q
The inner query here groups your bids together, counts how many in each group, and then selects only those groups with more than 1 value.
The outer query simply counts the results of that query.
You can see how it works here: http://sqlfiddle.com/#!9/0c9e6/3
declare #t table (bid int,val int)
insert into #t (bid,val)values (1,0),(1,3),(2,4),(2,5),(2,6),(3,7)
;with cte as (
select bid,
val,ROW_NUMBER()OVER(PARTITION BY bid order by val )RN from #t
)
select COUNT( DISTINCT bid) from cte
where RN > 1
you need only 2 count one for checking the count of values for each id and the other for all ids who has more than one value, you don't need to use having:
SELECT COUNT(*)
FROM (
SELECT BID, COUNT(*) CNT
FROM your_table
GROUP BY BID
) q
WHERE CNT>1