mysql row numbering reset every different record values - mysql

My question is pretty similar to this one Auto number and reset count for each different column value
except that I can't make it work.
I have the table record:
ID(autoINC) plate_number
1 A
2 A
3 A
4 B
5 B
6 C
7 C
I want to display something like this adding additional field cc:
I have the table record:
ID(autoINC) plate_number count
1 A 1
2 A 2
3 A 3
4 B 1
5 B 2
6 C 1
7 C 2

You can have a correlated subquery which sequentially count the row which can be used as a rownumber.
SELECT A.ID,
A.plate_number,
(
SELECT COUNT(*)
FROM tableName c
WHERE c.plate_number = a.plate_number AND
c.ID <= a.ID) AS RowNumber
FROM TableName a
SQLFiddle Demo

Related

How to select 1:n related records which are minimum 2 per type in MySQL

I have the following database tables.
my_left_table
left_id name
1 A
2 B
3 C
my_right_tabe
right_id thing left_id_fk status
1 D 1 new
2 E 1 new
3 F 2 old
4 G 3 old
5 H 3 new
6 I 3 new
7 J 1 old
8 K 2 old
9 L 2 new
10 M 3 old
11 N 3 old
12 O 1 new
My desired result is as follow.
my_left_table
left_id name
3 C
How do I select the left records which its right records have AT LEAST 2 status is new AND 2 status is old. For example, left_id 1 is not the target because three of its right records have the status new but only one record has the status old.
So far I have is.
SELECT *, COUNT(my_right_tabe.left_id_fk) AS count_left_id_fk
FROM my_left_table
INNER JOIN my_right_tabe
ON my_left_table.id = my_right_tabe.left_id_fk
GROUP BY my_right_tabe.left_id_fk
Use the HAVING clause in MySQL
Like the following
SELECT my_left_table.left_id, my_left_table.name
FROM my_left_table
INNER JOIN my_right_tabe
ON my_left_table.left_id = my_right_tabe.left_id_fk
GROUP BY my_right_tabe.left_id_fk
HAVING SUM(my_right_tabe.status="new") >= 2 AND
SUM(my_right_tabe.status="old") >= 2
You can achieve desired results by first grouping the values and then check its total. If its >= 2 pull that record.
Here is the query
SELECT z.*
FROM
(
SELECT a.left_id, name, status, IF(COUNT(*) >=2, 1, 0) AS status_calc
FROM my_left_table a JOIN my_right_table b
ON a.left_id = b.left_id_fk
GROUP BY left_id, status
) z
GROUP BY z.left_id
HAVING SUM(status_calc) = 2;
Working Demo

Show Items even if 0 rows with group by

I'm trying to get the query below to show for each item for each store the amount of each of 4 items we have.
It works great, and I created the temporary table to try to increase speed but my problem is that if the table has no rows for a certain product that product does not show up at all.
I'd like to show all four products(prodNo) regardless of if there is actually any of rows for that specific store.
I researched this site and could not find something similar enough for me to figure it out.
CREATE TEMPORARY TABLE IF NOT EXISTS temp_invoice_dates AS
(
SELECT Invoice_detail.del_date,invoice_Detail.StoreNo,mast_stores.SDesc, invoice_Detail.ProdNo,sold_qty,retn_price,retn_qty,sold_price FROM Invoice_detail
LEFT JOIN mast_stores on invoice_detail.StoreNO=mast_stores.Snum
LEFT JOIN invoice on invoice_detail.Del_Date=invoice.Del_Date and invoice_detail.Invoice_No=invoice.Invoice_No
WHERE Cnum IN ('200','210') AND invoice_detail.Del_Date >= "2016-03-01" AND invoice_detail.Del_Date < "2016-04-01"
);
SELECT
temp_invoice_dates.StoreNo,
temp_invoice_dates.SDesc,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%Y') as Year,
DATE_FORMAT(temp_invoice_dates.Del_Date,'%M') as Month,
temp_invoice_dates.ProdNo,
mast_items.IDesc,
SUM(sold_qty) as TotalIn,
SUM(retn_qty) as TotalOut,
ROUND(SUM((sold_qty*sold_price)-(retn_qty*retn_price)),2) as NetSales,
CONCAT(ROUND(SUM(retn_qty)/SUM(sold_qty),2)*100,'%') as StalePerc
FROM mast_Items
LEFT JOIN temp_invoice_dates on temp_invoice_dates.ProdNo=mast_items.Inum
WHERE mast_items.Inum in ('3502','3512','4162','4182')
GROUP BY temp_invoice_dates.StoreNo, ProdNo
ORDER BY temp_invoice_dates.StoreNo, ProdNo;
Drop table temp_invoice_dates;
Results are similar to:
StoreNo Product Count....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 4 4
3 2 33
3 3 3
Where as I'd like it to be
StoreNo Product Count ....
1 1 1
1 2 5
1 3 2
1 4 1
2 1 14
2 2 1
2 3 0
2 4 4
3 1 0
3 2 33
3 3 3
3 4 0
Something like this should work.
SELECT sp.StoreNo, sp.ProdNo
, ...stuff...
, sp.IDesc, sp.SDesc
, ...more stuff...
FROM (
SELECT i.Inum AS ProdNo, s.Snum AS StoreNo
, i.IDesc, s.SDesc
FROM mast_Items AS i, mast_stores AS s
WHERE i.Inum IN ('3502','3512','4162','4182')
) AS sp
LEFT JOIN temp_invoice_dates AS tid
ON sp.ProdNo = tid.ProdNo
AND sp.StoreNo = tid.StoreNo
GROUP BY sp.StoreNo, sp.ProdNo
ORDER BY sp.StoreNo, sp.ProdNo
;
Normally I recommend against cross joins (as seen in the subquery) but in this case it is exactly what is needed. If the query is slow, you can instead insert the subquery results into a temp table beforehand, index that, and then use the temp table in place of the subquery.
(Edit: should use sp fields when available for grouping and results)

MySQL UPDATE with GROUP and ORDER

I'm trying to make an update on a table so that it can increment the values on 1 column depending on another's order.
Here's how it'd go
ID GROUP_ID ORDER(Desired) ORDER(NOW)
1 1 1 2
2 1 2 3
3 1 3 1
4 2 1 2
5 2 2 1
6 3 1 1
7 3 2 1
8 3 3 2
So what I need is for each ID, to update the ORDER column so it can be consecutive, starting from 1, within each GROUP_ID.
I have found some solutions to similar problems regarding the updates and orders, but none that uses multiple orders for groups within the same table.
Hope I illustrated the problem right. Thanks in advance
You can do it by "ranking" the rows over again. Mysql doesn't support window functions but you can achieve the same results with join and count like this:
UPDATE YourTable t
INNER JOIN(SELECT s.id,s.group_id,count(*) as cnt
FROM YourTable s
INNER JOIN YourTable ss
ON(s.group_id = ss.group_id and s.id >= ss.id)
GROUP BY s.id,s.group_id) tt
ON (t.id = tt.id and t.group_id = tt.group_id)
SET t.order = tt.cnt

Sum rows after comparing one row with multiple rows

I have two tables that will be a and b. I want to compare number in a to number in b where they share an ID. a has a single row, while b has multiple. If the sum of b is less than a, then that row of a should be added to the total sum, otherwise it should be skipped.
Table a
ID Number
4 50
5 60
6 70
Table b
ID Number SharedID
1 30 4
2 25 4
3 50 5
4 5 5
5 30 6
6 10 6
Using that example: b 1 and 2 are greater than a 4, so it wouldn't be counted. b 3 and 4 are less than a 5 so it would count. b 5 and 6 are less than a 6, so it would count. The total should be 130.
I'm having trouble with doing a comparison of one row to multiple and then only summing some of the numbers.
This should do the job:
select sum(Number)
from a
where Number > (select sum(Number) from b where b.SharedID = a.ID)
Try this query:
SELECT SUM(a.Number)
FROM a INNER JOIN
(
SELECT b.SharedID, SUM(b.Number) AS theSum
FROM b
GROUP BY b.SharedID
) t
ON a.ID = t.SharedID
WHERE t.theSum < a.Number
The conceptually easiest option is to create a temporary table containing the sums of Table b, and then to JOIN that back to Table a. The WHERE clause restricts your total to only a Number values which are greater than the b sum.
select SUM(number) from(
select case when(aa.number>(select SUM(bb.number)
from bb where bb.sharedid=aa.id))then aa.number else 0 end as number from aa )abc
This should do the trick

Access Totals Query Not Necessarily Returning First Record

I have a table of data like this:
id user_id A B C
=====================
1 15 1 2 3
2 15 1 2 5
3 20 1 3 9
4 20 1 3 7
I need to remove duplicate user ids and keep the record that sorts lowest when sorting by A then B then C. So using the above table, I set up a temp query (qry_temp) that simply does the sort--first on user_id, then on A, then on B, then on C. It returns the following:
id user_id A B C
====================
1 15 1 2 3
2 15 1 2 5
4 20 1 3 7
3 20 1 3 9
Then I wrote a Totals Query based on qry_temp that just had user_id (Group By) and then id (First), and I assumed this would return the following:
user_id id
===========
15 1
20 4
But it doesn't seem to do that--instead it appears to be just returning the lowest id in a group of duplicate user ids (so I get 1 and 3 instead of 1 and 4). Shouldn't the Totals query use the order of the query it's based upon? Is there a property setting in the query that might impact this or another way to get what I need? If it helps, here is the SQL:
SELECT qry_temp.user_id, First(qry_temp.ID) AS FirstOfID
FROM qry_temp
GROUP BY qry_temp.user_id;
You need a different type of query, for example:
SELECT tmp.id,
tmp.user_id,
tmp.a,
tmp.b,
tmp.c
FROM tmp
WHERE (( ( tmp.id ) IN (SELECT TOP 1 id
FROM tmp t
WHERE t.user_id = tmp.user_id
ORDER BY t.a,
t.b,
t.c,
t.id) ));
Where tmp is the name of your table. First, Last, Min and Max are not dependent on a sort order. In relational databases, sort orders are quite ephemeral.