counting with conditions in mysql - mysql

im a bit stuck in a quite simple query
i have these 4 columns in the table
id1 (unique), id2 (can repeat) , updated (boolean), updated_on
what i want now is to get a summary in the form
id2, count of updates , max (updated_on)
in short i want the result sorted by the recent updated_on while counting all rows for this id2 where update=1
and for ids that donot have any update=1, show 0, with the max updated_on
______________________
id2|_count__|___date__
1 | 0 | 11/03/05,
3 | 5 | 11/03/04,
6 | 3 | 11/03/03,
2 | 0 | 11/03/02,
i used this query :
select id2, count(updated),max(updated_on) from table
where updated=1
group by need_id_to
but this query doesnot bring results where count would be 0 (for obvious reasons because im adding a condition in the where clause)

A boolean field is 1 for true and 0 for false.
You can use this to get the count of all updated = true rows.
SELECT
id2
, SUM(updated) as updates
,MAX(updated_on) as last_update
FROM table1
GROUP BY id2
ORDER BY last_update DESC

select id2,
count(case
when updated=1 then updated
else null
end) updates_count,
max(updated_on) last_updated
from table
group by id2
order by last_updated desc

select id2,
SUM(CASE WHEN updated=1 THEN 1 ELSE 0 END) AS UpdatedCount,
max(updated_on)
from table
group by id2

Related

How to fetch rows from which sum of a single integer/float column sums upto a certain value

I have a table. It has the following structure
goods_receiving_items
id
item_id
quantity
created_at
I am trying to fetch rows against which have the following conditions
Has one item_id
When the sum of the quantity column equals a certain value
So for example I have the following data
+----+---------+----------+------------+
| id | item_id | quantity | created_at |
+----+---------+----------+------------+
| 1 | 2 | 11 | 2019-10-10 |
| 2 | 3 | 110 | 2019-10-11 |
| 3 | 2 | 20 | 2019-11-09 |
| 4 | 2 | 5 | 2019-11-10 |
| 5 | 2 | 1 | 2019-11-11 |
+----+---------+----------+------------+
I have tried the following query:
SET #sum:= 0;
SELECT item_id, created_at, (#sum:= #sum + quantity) AS SUM, quantity
FROM goods_receiving_items
WHERE item_id = 2 AND #sum<= 6
ORDER BY created_at DESC
If I don't use ORDER BY, then the query will give me ID '1'. But if I use ORDER BY it will return all the rows with item_id = 2.
What should be returned are IDs '5' and '4' exclusively in this order
I can't seem to resolve this and ORDER BY is essential to my task.
Any help would be appreciated
You should use the order by on the resulting set
you could do this using a subquery
SET #sum:= 0;
select t.*
from t (
SELECT item_id
, created_at
, (#sum:= #sum + quantity) as sum
, quantity
FROM goods_receiving_items
WHERE item_id = 2 AND #sum<= 6
) t
ORDER BY created_at DESC
You should try an INNER JOIN with SELECT min(created_at) or SELECT max(created_at)
From MYSQL docs:
...the selection of values from each group cannot be influenced by
adding an ORDER BY clause. Sorting of the result set occurs after
values have been chosen, and ORDER BY does not affect which values the
server chooses.
The answers on the following might help in more detail: MYSQL GROUP BY and ORDER BY not working together as expected
After searching around, I have made up the following query
SELECT
t.id, t.quantity, t.created_at, t.sum
FROM
( SELECT
*,
#bal := #bal + quantity AS sum,
IF(#bal >= $search_number, #doneHere := #doneHere + 1 , #doneHere) AS whereToStop
FROM goods_receiving_items
CROSS JOIN (SELECT #bal := 0.0 , #doneHere := 0) var
WHERE item_id = $item_id
ORDER BY created_at DESC) AS t
WHERE t.whereToStop <= 1
ORDER BY t.created_at ASC
In the above query, $search_number is a variable that holds the value that has to be reached. $item_id is the item we are searching against.
This will return all rows for which the sum of the column quantity makes up the required sum. The sum will be made with rows in descending order by created_at and then will be rearranged in ascending order.
I was using this query to calculate the cost when a certain amount of items are being used in an inventory management system; so this might help someone else do the same. I took most of the query from another question here on StackOverflow

what is an efficient query for this task

I have a data file that looks like this
item_id | status
1 | null
2 | null
2 | new
3 | new
4 | null
4 | new
5 | null
Notice that item 2 and 4 have both 2 status: null and new.
I want to create a query that would extract only item_id with 1 status, which is null. So, i want my query to extract only 1 and 5.
I ended up doing this, but this doesn't look efficient:
1.List items with null status
create table query_1 as
select * from table1 where status = 'null';
2.List item with new status
create table query_2 as
select * from table1 where status = 'new';
3.select all results from query 1, excluding any id found from the results of query 2
select * from query_1 where item_id not in (select item_id from query_2)
Am I over thinking this? Is there a simpler query that can accomplish this?
First you have to check for null values with IS NULL. =null or ='null' won't work.
SELECT item_id, MAX(status)
FROM table1
GROUP BY item_id
HAVING MAX(status) IS NULL
select item_id
from table1
group by item_id
having count(*) = 1 and status is null
You can use self-join. What you need to do is remove the item_id's having new values. The remaining entries would be would you want. So you can frame your query as such :
SELECT item_id,
status
FROM tableName
WHERE item_id NOT IN (SELECT item_id
FROM #tab
WHERE status = 'new')
You can see this here -> SQL Fiddle Example
SELECT item_id FROM items
WHERE status IS NOT NULL
AND item_id NOT IN
(SELECT item_id FROM items
WHERE status IS NULL
)
You could use DISTINCT in this instance
SELECT DISTINCT item_id FROM items WHERE status IS NULL;

MySQL order by first column, sorted by second column

I'm trying to get the correct ORDER BY for my MySQL query, however I can't get the order by correct.
I have two columns:
breaking_news = values are NULL or 1
news_published_dt = values are DATETIME
How can I sort so that the first output are breaking_news NOT NULL sorted by DATETIME, and then the rest afterwards is just ordered by DATETIME?
I've tried this, but it gave me no output
ORDER BY CASE WHEN n.breaking_news IS NOT NULL THEN 1 ELSE 2 END, n.news_published_dt DESC
Looks like, you are looking for this:
SELECT
*
FROM
tableName
ORDER BY
breaking_news DESC,
news_published_dt ASC
SELECT * FROM table_name ORDER BY news_published_dt DESC
select * from
(select *, 1 Shortby from table 1 where (breaking_news is null)
union all
select *, 2 Shortby from table 1 where (breaking_news=1)
) a
order by Shortby ,news_published_dt Desc
SORT BY in MySQL works differently than what you (me included) would be expected. You cannot do a sort by of two columns and have each of the first sorted by columns sorted according to the second.
DOES NOT WORK:
ORDER BY breaking_news, news_published_dt
RESULT:
breaking_news | news_published_dt
1 | 2019-04-17
1 | 2019-04-04
null | 2019-05-01
null | 2019-05-06
Notice that the nulls are sorted correctly, however where breaking_news is 1; the results are not sorted according to what the poster wants.
The only way that I have found to accomplish this; query for the wanted boolean result individually and then union the two together.
THIS DOES WORK:
(SELECT * FROM news_table WHERE breaking_news = 1 ORDER BY news_published_dt)
UNION
(SELECT * FROM news_table WHERE breaking_news <> 1 ORDER BY news_published_dt)
RESULT:
breaking_news | news_published_dt
1 | 2019-04-04
1 | 2019-04-17
null | 2019-05-01
null | 2019-05-06
For a more thorough explanation of this, check out Edwin Wang's explanation
USE This
ORDER BY CASE WHEN n.breaking_news IS NOT NULL THEN n.breaking_news ELSE 'zzzzzzzzzzzzzzzzzzzzzz' END, n.news_published_dt DESC

select rows based on next row in mysql

I have a table like this :
Type | Time
1 | 234234
2 | 234235
1 | 234238
3 | 234239
4 | 234240
1 | 234242
2 | 234245
I want to count number of all those rows where type=1 and next row's type=2.
For ex : The result here is 2.
I don't know how to put where clause on next row.
You should be able to implement user defined variables to get the total:
select count(*) Total
from
(
select type,
#row:=(case when #prev=1 and type=2 then 'Y' else 'N' end) as Seq,
#prev:=type
from yourtable, (SELECT #row:=null, #prev:=null) r
order by time, type
) src
where Seq = 'Y'
See SQL Fiddle with Demo

MySQL merge amounts in a 2 rows

I'm looking to create a sql statement that will update a large set of data.
What I have is a table like
id, transid, amount, narative1, narative 2, total, active
1 1234 23.2 NULL NULL NULL 1
2 1234 120.33 NULL NULL NULL 1
3 1235 98.00 NULL NULL NULL 1
When there are two rows with the same transid I need to total them put the result in the total column of the first one with that transid and put the second amount in naritive2 of the first instance as well as make the second one inactive. It should ignore single rows for a transid.
The result of what I want to do should be:
id, transid, amount, narative1, narative 2, total, active
1 1234 23.2 NULL 120.33 143.53 1
2 1234 120.33 NULL NULL NULL 0
3 1235 98.00 NULL NULL NULL 1
I know a bit of a thong twister but..
Ideally I'd like to do this in just a MySQL statements. So I don't mind having to do multiple sql statements but I want to avoid connecting it to PHP etc. Its a very large set of data.
This will update only those transactions that have exactly 2 rows (not 1 and not 3 or more).
UPDATE mytable mtu
JOIN (
SELECT minid, maxid, mtmin.amount AS minamt, mtmax.amount AS maxamt
FROM (
SELECT MIN(id) AS minid, MAX(id) AS maxid
FROM mytable mti
GROUP BY
transid
HAVING COUNT(*) = 2
) mt
JOIN mytable mtmin
ON mtmin.id = minid
JOIN mytable mtmax
ON mtmax.id = maxid
) mts
ON id IN (minid, maxid)
SET narative2 = CASE id WHEN minid THEN minamt ELSE NULL END,
total = CASE id WHEN minid THEN minamt + maxamt ELSE NULL END,
active = (id = minid)