given the following table:
id (desc) | amount
------------------
9 | 3
8 | 2
7 | 1 <- RETURN THIS ROW
6 | 0
5 | 1
4 | 0
3 | 2
2 | 1
1 | 0
I need to return only one row - that one with the id 7
Rules:
- the most recent entry have an amount bigger than 0
- should return the row after the first amount 0 occurence
That way if I have:
id (desc) | amount
------------------
4 | 0
3 | 0
2 | 1
1 | 0
It will not show any row.
You can use window functions:
select t.*
from (select t.*,
max(case when amount = 0 then id end) over () as last_0_id
from t
) t
where id > last_0_id
order by id asc
limit 1;
Or, without window functions:
select t.*
from t join
(select max(t2.id) as id
from t t2
where t2.amount = 0
) t2
on t.id > t2.id
order by id asc
limit 1;
Here is a db<>fiddle
This is probably faster than using lead(), actually.
Related
Table1 contains a column with cumulated values (all positive integers):
id ValuesCum
1 5
2 8
3 20
I would like to write a statement that returns an extra column with the incremented values for each row. The output should read something like:
id ValuesCum ValuesInc
1 5 (5)
2 8 3
3 20 12
Does anyone have a solution for this?
If you are running MySQL 8.0, you can use window function lag() for this:
select
t.*,
ValuesCum - lag(ValuesCum, 1, 0) over(order by id) ValuesInc
from mytable t
In earlier versions, an alternative is a correlated subquery:
select
t.*,
ValuesCum - (
select coalesce(max(t1.ValuesCum), 0)
from mytable t1
where t1.id < t.id
) ValuesInc
from mytable t
You can use a correlated subquery to get the value of ValuesCum of the previous id:
select t.*,
t.ValuesCum -
coalesce((select ValuesCum from tablename where id < t.id order by id desc limit 1), 0) ValuesInc
from tablename t
See the demo.
Results:
| id | ValuesCum | ValuesInc |
| --- | --------- | --------- |
| 1 | 5 | 5 |
| 2 | 8 | 3 |
| 3 | 20 | 12 |
I've tried a few PROCEDURES and LOOPS, but i'm having trouble getting my results.
I have a table of 19,000 records that looks like this:
id | seq | custom_id
1 | 0 | 123
2 | 0 | 124
3 | 1 | NULL
4 | 0 | 125
5 | 1 | NULL
6 | 2 | NULL
7 | 3 | NULL
My goal is:
id | seq | custom_id
1 | 0 | 123
2 | 0 | 124
3 | 1 | 124-1
4 | 0 | 125
5 | 1 | 125-1
6 | 2 | 125-2
7 | 3 | 125-3
So if seq is 0 it will have a custom ID. if seq is not 0 I would like to get the custom id and concat -seq to the end.
In a Correlated Subquery, we can get the previous (and closest) custom_id value where the seq is 0.
Now, we simply need to use Concat() function to concatenate the previous custom_id value with the current row's seq value, to get the new custom_id.
Try the following query to Select the data (DB Fiddle DEMO):
SELECT
t1.id,
t1.seq,
CASE WHEN t1.seq = 0 THEN t1.custom_id
ELSE CONCAT((SELECT t2.custom_id
FROM your_table AS t2
WHERE t2.id < t1.id AND
t2.seq = 0
ORDER BY t2.id DESC LIMIT 1), '-', t1.seq)
END AS custom_id
FROM your_table AS t1
However, based on your comments, it seems that you are interested in Updating the custom_id column at once. In MySQL, using subquery on the same table (which is being updated as well), is possible via Derived Tables approach.
We determine the modified custom_id for id where seq <> 0 in a sub-select result set (Derived table), and then Join it back to the main table for update.
Try the following for Updating the data (DB Fiddle DEMO):
UPDATE
your_table AS tab
JOIN
(
SELECT
t1.id,
CONCAT((SELECT t2.custom_id
FROM your_table AS t2
WHERE t2.id < t1.id AND
t2.seq = 0
ORDER BY t2.id DESC LIMIT 1),
'-', t1.seq) AS custom_id
FROM your_table AS t1
WHERE t1.seq <> 0
) AS dtab ON dtab.id = tab.id
SET tab.custom_id = dtab.custom_id
WHERE tab.seq <> 0;
I have three tables in database:
Table: article
id | code | name | quantity | stock_date
--------------------------------------------------
1 1dfod Article name 10 2016-04-01
Table: selling
id | client_id | selling_type_id | selling_date | selling_status
----------------------------------------------------------------
1 1 1 2016-04-02 1
2 1 1 2016-04-03 1
3 1 1 2016-04-04 1
Table: selling_detail
id | selling_id | article_id | quantity
-------------------------------------
1 1 1 2
2 1 1 3
3 1 1 1
4 2 1 3
5 3 1 1
at the end I would have a stock record for this article like this:
date | in_stock (item in stock) | out_stock (sum of item sold)
----------------------------------------------------------------------
2016-04-01 10 0
2016-04-02 0 6
2016-04-03 0 3
2016-04-04 0 1
All mysql queries to my knowledge do not give me this result.
Here is my code:
SELECT SUM(sd.quantity) out_stock, s.search_date, ifnull(ss.quantity, 0) in_stock
FROM selling_detail sd JOIN selling s ON (sd.selling_id = s.id)
LEFT JOIN shop_stock ss ON (ss.search_date = s.search_date) WHERE (sd.shop_stock_id = 1)
GROUP BY s.search_date;
SELECT date,SUM(in_stock) in_stock,SUM(out_stock) out_stock FROM
(
SELECT stock_date date,quantity in_stock,0 out_stock FROM article
UNION
SELECT selling_date,0,quantity FROM selling JOIN selling_detail ON selling_detail.selling_id = selling.id
) x
GROUP BY date;
As you are trying to combine similar data from two very different tables, you'll probably be staring down the barrel of a UNION ALL.
Something along these lines should get you started:
SELECT *
FROM (
SELECT a.stock_date `date`,
SUM(a.quantity) `in_stock (item in stock)`,
0 `out_stock (sum of item sold)`
FROM article a
WHERE a.id = :article_id
GROUP BY `date`
UNION ALL
SELECT s.selling_date,
0,
SUM(sd.quantity)
FROM selling s
JOIN selling_detail sd
ON sd.selling_id = s.id
AND sd.article_id = :article_id
/* WHERE s.selling_type = ??
AND s.selling_status = ?? /* If necessary */
GROUP BY `date`
) sr
ORDER BY `date`
I'm currently trying to make a mysql query that will count the number of zeros and ones per item, in the following way:
Table:
ID | PollID | Value
------------------------------------
1 | 1 | 1
2 | 1 | 1
3 | 2 | 0
4 | 2 | 1
5 | 1 | 0
And the result I want is:
Poll | one | zero
----------------------------------
1 | 2 | 1
2 | 1 | 1
Thanks for the help!
This is the shortest possible answer in MySQL because it supports boolean arithmetic.
SELECT PollID,
SUM(value = 1) AS `One`,
SUM(value = 0) AS `Zero`
FROM tableName
GROUP BY PollID
SQLFiddle Demo
select z.pollid,z.ones,s.zeros
from (select a.pollid,count(a.value) as ones from test a
where a.value=1
group by a.pollid) z
left join
(select b.pollid,count(b.value) as zeros from test b
where b.value=0 group by b.pollid) s
on z.pollid=s.pollid;
try this
select table.pollid,
Switch(table.value Like 1, 1)AS one,
Switch(table.value Like 0, 1)AS zero
from table
group by pollid
ID stone_free original_stone_id
------- | ---------- | -------------------
1 | 0 | 1
2 | 1 | 2
3 | 1 | 1
I would like to return rows from the table only if stone_free equals 0 and there is no corresponding original_stone_id in other rows for each row. So for example in the above example row 1 has stone_free as 0 and there is a corresponding original_stone_id in row 3, therefore the query shouldn't return any rows.
In the example below row 1 has stone_free as 0 but there is no corresponding original_stone_id in the other row, therefore the query should return row 1.
ID stone_free original_stone_id
------- | ---------- | -------------------
1 | 0 | 1
2 | 1 | 2
A simple LEFT JOIN should do it;
SELECT a.*
FROM Stones a
LEFT JOIN Stones b ON a.ID<>b.ID AND a.original_stone_id = b.original_stone_id
WHERE b.ID IS NULL AND a.stone_free=0
Demo here.
I'm not sure if it'll work on MySQL but give a shot to it
select *
from tbl
where stone_free = 0 and
(
select count(tab.original_stone_id)
from tbl tab
where tab.original_stone_id = tbl.original_stone_id
) = 1
Select * from tablename t1
Where stone_free = 0
And Not Exists (Select Id from tablename t2 where t2.original_stone_id = t1.original_stone_id And t2.Id <> t1.Id)