Mysql select one more row for each group - mysql

Hi there is an exemple of the result that i want
no : order number
dataType : 1 = the number of piece done for a specific week
2 = the number of piece remaining
done : number of piece done
total : number of piece
I would like to make a single query. The first part of this query would return me all the rows with a dataType 1 and the other part would return me all rows with dataType 2. The dataType 2 would be there only once per orders, it is only there to show what is remaining to do.
I have done this query by duplicating my big select and using a UNION, but there is a way to use all the order number returned in the first query to get what is remaining to do for each order by adding a new row.
thank you I hope my question is clear
I have made an sqlfiddle to show you the query that i did
http://sqlfiddle.com/#!9/26a9d/15
SELECT
no,
SUM(vCountDone) done,
(SELECT SUM(vCountTotal) FROM table1) total,
week,
'1' AS dataType
FROM
table1
GROUP BY DATE(week)
UNION ALL SELECT
no,
SUM(vCountTotal) - SUM(vCountDone) done,
(SELECT SUM(vCountTotal) FROM table1) total,
MAX(week),
'2' AS dataType
FROM
table1 t2

Related

counting all records in table and putting it into a variable inside mysql itself

I have a table named financial_trans which consist of
id (AI,INT)
amount (DOUBLE)
acadYear (VARCHAR) // probably '2020-2021'
now I want to count the similar acadYear using group by and store it into a mysql variable and my query for that is
SELECT s.total as total
INTO #year
FROM (
SELECT COUNT(acadYear) as total
FROM financial_trans
GROUP BY acadYear
) s
but throws an error like below,
#1172 - Result consisted of more than one row
Your sub-statement SELECT COUNT(acadYear) as total FROM financial_trans GROUP BY acadYear yields more then 1 row, so it can fit into variable #year.
That basically means that you have records for more then 1 distinct year in your financial_trans table. If you need to count records only for specific year, just add WHERE acadYear = XXXX into subquery. Or even better, SELECT COUNT(1) FROM financial_trans WHERE acadYear = XXXX.
Side note: DOUBLE is not ideal column type for financial records, you should use DECIMAL

Limiting the count query in MySQL?

I am trying to do a simple test where I'm pulling from a table the information of a specific part number as such:
SELECT *
FROM table_name
WHERE part_no IN ('abc123')
This returns 25 rows. Now I want to count the number that meet the "accepted" condition in a specific column but the result is limited to only the 10 most recent. My approach is to write it as follows:
Select Count(*)
FROM table_name
WHERE part_no IN ('abc123') AND lot IN ('accepted')
ORDER BY date DESC
LIMIT 10
I'm having a hard time to get the ORDER BY and LIMIT operations to work. I could use help just getting it to limit appropriately, and I can figure out the rest from there.
Edit: I understand that the operations are happening on the COUNT which only returns one row with a value; but I put the second clip to show where I am stuck in my thought process.
Your query SELECT Count(*) FROM ... will always return exactly one row.
It's not 100% clear what exactly you want to do, but if you want to know how many of the last 10 have been accepted, you could use a subquery - something like:
SELECT COUNT(*) FROM (
SELECT lot
FROM table_name
WHERE part_no IN ('abc123')
ORDER BY date DESC
LIMIT 10
)
WHERE lot IN ('accepted')
The inner query will return the 10 most recent rows for part abc123, then the outer query will count the accepted ones.
There are also other solution (for example, you could have the inner query output a field that is 0 when the part is not accepted and 1 when the part is accepted, then take the sum). Depending on which exact dialect/database you are using, you may also have more elegant options.
Select count returns ONE ROW therefore the ORDER BY and the LIMIT will not work on the results

SQL MIN() selecting Data. ORDER table correctly

I have 2 questions. First of all I have a MySQL Database with the rows: id(AUTO_INCREMENT PRIMARY KEY), name and time. This database represents the times of a race. I would like to select the name and time where the time is the smallest.
SELECT name, MIN(time) as time FROM race GROUP BY TIME;
This query gives me all times and names as long as there are no duplicates in the names. I however only want the fastest time and the name in that row.
Then when I submit my time i would like to know on what place I am. Will ORDER BY TIME keep each ID of each row the same or can I just ORDER table BY time and then select row where ID= 1?
If it's possible to have multiple entries with the same time, I would use a nested query like this, because limiting the result set to 1 may exclude a name.
select name, time from race where time = (select min(time) from race)
If you want to know what place a given time is in, just count the number of entries that have times less than it.
select count(*) + 1 as place from race where time < [your time]
For your first question, what you want is to select the 'least' time.
Here is, what I think, the clearest way to do that, which uses the LIMIT function to only return 1 row.
MySQL:
SELECT name, time
FROM race
ORDER BY time asc
LIMIT 1;
MS SQL:
SELECT TOP 1 name, time
FROM race
ORDER BY time asc

Make MIN() return multiple rows?

Is there a way to return more than one row based on the idea of this query:
SELECT MIN(colname) AS value FROM table_name
Thanks
Dave
If you're trying to select the rows with the N (say, 10) smallest values in some column, you could do something like:
SELECT * FROM table_name ORDER BY colname ASC LIMIT 10;
Apologies if I've misunderstood the question.
No, there is no way to return more than 1 rows for this very query (the one you included in the example)
If you want to be doubly sure, add a "LIMIT 1" at the end. (that would limit the result set to 1 row, but not required here)
EDIT:
To answer your question "Is there any other query that can return say 5 rows based on each row having MIN values in one column", yes there is. You need to use a 'group by' syntax, for example:
SELECT category, MIN(price) AS value FROM table_name group by category
To select multiple rows one solution is to find all rows with values that match the previously determined minimum value:
SELECT *
FROM tableA
JOIN
(SELECT MIN(colname) AS minvalue FROM tableA) B
ON tableA.colname = B.minvalue
This solution differs from GROUP BY in that it will not otherwise aggregate (or limit) the data in the resultset. In addition, this particular solution does not consider the case of NULL being the "minimum value".
Happy coding.

MySQL INSERT/SELECT subquery syntax

Just can't wrap my head around the proper syntax for this one. Below is my query, with a plain english explanation of my subquery, in the spot where I think I'd want it to execute.
mysql_query("INSERT INTO donations(
tid,
email,
amount,
ogrequest,
total
)
VALUES (
'".esc($p->ipn_data['txn_id'])."',
'".esc($p->ipn_data['pay_email'])."',
".(float)$amount.",
'".esc(http_build_query($_POST))."',
Here I want to select the row with the max date, get the value of the "total" column in that row, and add $amount to that value to form the new "total" for my newly inserted row.
)");
Can anyone help a bro out?
The real answer is you should not be storing the total in a column in this table. It isn't really any useful information. What you should be storing is the current date, and then calculating the total via SUM and GROUP BY. If it's something that you need to access often, then cache the value elsewhere.
Why do you need the total in any of the rows before the last one? It is just wasted data, and it can be easily regenerated from the table.
Why do you want to store the total in this column. What value does this data add to your schema? The important thing to note here is that the total is NOT a property of the individual transaction. The total is a property of an aggregated subset of individual transactions.
Also - make sure you are using DECIMAL and not FLOAT for your monetary column types in MySQL if you aren't. FLOAT values could result in rounding errors depending on what you are doing, which is something there is no reason to risk when money is involved.
I don't have access to a MySQL server to verify what I created, but try this:
INSERT INTO donations
(
tid,
email,
amount,
ogrequest,
total
)
SELECT
'".esc($p->ipn_data['txn_id'])."',
'".esc($p->ipn_data['pay_email'])."',
".(float)$amount.",
'".esc(http_build_query($_POST))."',
total + '".esc($amount)."'
FROM
ORDER BY date DESC
LIMIT 1
Instead of using a direct "INSERT INTO (...) VALUES (...)" I used a "INSERT INTO (...) SELECT ...". The SELECT statement retrieves the row with the highest date (ORDER BY date DESC LIMIT 1), then the total field is accessed and added with the value of $amount.
mysql_query("INSERT INTO donations(
tid,
email,
amount,
ogrequest,
total
)
VALUES (
'".esc($p->ipn_data['txn_id'])."',
'".esc($p->ipn_data['pay_email'])."',
".(float)$amount.",
'".esc(http_build_query($_POST))."',
(select max(total) from donations) + ".(float)$amount."
)");
Your subquery could look like this:
SELECT total
FROM donations
WHERE tid = <x>
ORDER BY date DESC
LIMIT 1
This of course requires that you have a date column in your table. If you run this one (without the outer query you already have), it should come back with a single row, single column result containing the value of latest total for tid = <x>.
If there's not already a row for txn = <x> in the table, then it will obviously return no row at all. When used as a subquery for your INSERT statement, you should probably check for NULL and replace it with a numeric 0 (zero). This is what IFNULL() can do for you.
Combining this and what you already have:
mysql_query("INSERT INTO donations(
tid,
email,
amount,
ogrequest,
total
)
VALUES (
'".esc($p->ipn_data['txn_id'])."',
'".esc($p->ipn_data['pay_email'])."',
".(float)$amount.",
'".esc(http_build_query($_POST))."',
IFNULL(SELECT total
FROM donations
WHERE id = ".esc(p->ipn_data[txn_id']."
ORDER BY date DESC
LIMIT 1),0) + ".esc($p->ipn_data['value']
)");