MySQL: Select multiple columns and total sum in one column - php

I've a table like:
-----------+------|
product_id |price |
-----------+------|
1 + 5 |
-----------+------|
2 + 15 |
-----------+------|
3 + 25 |
-----------+------|
I need the output like:
-----------+------|
product_id |sum |
-----------+------|
1 + 45 |
-----------+------|
2 + 45 |
-----------+------|
3 + 45 |
-----------+------|
My current query:
SELECT product_id, (SELECT SUM(price) FROM tableName) `sum` FROM tableName.
Is it possible to do this without using 2 SELECT queries or GROUP_CONCAT ?
Please help.
Thanks in advance!
Note: I've thousands of rows in my table and more conditions (to include other table data) will be added to this query.

Just use group by.
SELECT
product_id, (SELECT SUM(price) FROM tableName) `sum`
FROM
tableName
group by .

Use a query like this:
SELECT *, sum(price) AS sum FROM table WHERE condition = value

SELECT product_id , sum(price) AS sum FROM table WHERE condition = value
try not using sub query in select statement.

You can try this code
select product_id, (select sum(price) from PRODUCTS) as sum FROM products

Related

I need help writing a sql query to concat multiple fields

I have table with following information
id | order_id | batch_id | bucket_id | menu_id | product_id | type_id | size
1 | 1 | 1 | 1 | 1 | 1 | 1 | small
2 | 1 | 1 | 1 | 1 | 5 | 1 | small
3 | 1 | 1 | 1 | 1 | 5 | 1 | medium
I want to achieve following
order_id | batch_id | product1 | product5
1 | 1 | 1 x small| 1 x small, 1 medium
Is this possible to write a query to achieve this?
It's possible in MySQL using this kind of query:
SELECT order_id, batch_id,
GROUP_CONCAT(CASE WHEN product_id=1 THEN CONCAT(type_id,' x ', size) END) AS product1,
GROUP_CONCAT(CASE WHEN product_id=5 THEN CONCAT(type_id,' x ', size) END) AS product5
FROM table1
GROUP BY order_id, batch_id
The problem with this is that it's not dynamic so if you have hundreds, thousands of products, the query will be very hard to maintain. One possible solution in MySQL is using prepared statement. Here is an updated example after #ggordon spotted that my previous attempt show duplicates:
SET #columns := (SELECT GROUP_CONCAT(CONCAT("GROUP_CONCAT(CASE WHEN product_id=",product_id,"
THEN CONCAT(cnt,' x ', size) END)
AS product",product_id,"
"))
FROM (SELECT DISTINCT product_id FROM table1) t1);
SET #query := CONCAT('SELECT order_id, batch_id, ',#columns,'
FROM (SELECT product_id, order_id, batch_id, size, COUNT(*) cnt
FROM table1 GROUP BY product_id, order_id, batch_id, size) t1
GROUP BY order_id, batch_id');
PREPARE stmt FROM #query ;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
There are 2 variables being used in there and I named each variable to represent what is it (hopefully).
Demo fiddle
The following query would return the desired data you would need
SELECT
order_id,
batch_id,
product_id,
concat(
count(product_id),
' x ',
size
) as size_cnt
FROM
t1
GROUP BY
order_id,
batch_id,
product_id,
size;
order_id
batch_id
product_id
size_cnt
1
1
1
1 x small
1
1
5
1 x small
1
1
5
1 x medium
View working demo on DB Fiddle
However, in order to get it in the desired format, you would need to pivot the data. You could achieve this with the assistance of group_concat as shown in the sql example below:
SELECT
order_id,
batch_id,
-- we can generate from here
REPLACE(
GROUP_CONCAT(
',',
CASE
WHEN product_id=1 THEN size_cnt
END
),
',,',
','
) as product1,
REPLACE(
GROUP_CONCAT(
',',
CASE
WHEN product_id=5 THEN size_cnt
END
),
',,',
','
) as product5
-- to here. See explanation below
FROM (
SELECT
order_id,
batch_id,
product_id,
concat(
count(product_id),
' x ',
size
) as size_cnt
FROM
t1
GROUP BY
order_id,
batch_id,
product_id,
size
) t2
GROUP BY
order_id,
batch_id
order_id
batch_id
product1
product5
1
1
,1 x small
,1 x small,1 x medium
View working demo on DB Fiddle
However, as you can see, you would have to know the product_ids before hand for the desired columns.
If you are uncertain about the product ids that you will have, writing a dynamic query would be helpful here. You could start by getting all the product_ids.
I'm using the DB facade from Laravel here, however, you may use the Eloquent ORM or other methods to achieve the following:
//I have a collection of product ids i.e. `collect([1,5])` based on your example
$productIds = DB::select("select distinct product_id from t1")
->pluck('product_id');
Then generating a dynamic sql query to run on your table
$productExpression = DB::select("select distinct product_id from t1")
->pluck('product_id')
//for each product id let us return an sql expression
->map(function($productId){
return "
REPLACE(
GROUP_CONCAT(
',',
CASE
WHEN product_id=$productId THEN size_cnt
END
),
',,',
','
) as product$productId
";
})
//combine the expressions into one string
->join(",");
We can now create a combined query as
$combinedQuery="
SELECT
order_id,
batch_id,
$productExpression
FROM (
SELECT
order_id,
batch_id,
product_id,
concat(
count(product_id),
' x ',
size
) as size_cnt
FROM
t1
GROUP BY
order_id,
batch_id,
product_id,
size
) t2
GROUP BY
order_id,
batch_id;
";
//running the query to retrieve the results
$results = DB::select($combinedQuery);
Let me know if this works for you.
If you are using php with either PDO or mysqli you can get PHP to concat the fields.
$result = $db->query("SELECT * FROM TABLE");
while($row = $result->fetch_assoc()) {
//do stuff with data
$product .= $row["product_id"] . " x " . $row["size"].", ";
}

How to use group by on 2 different columns and use SUM function in mysql

I have this table:
and I want records like this:
Leave_detail_id emp_id leave_count
-------------------------------------
1 22 3
3 22 2
2 30 4
Please help me how to use multiple GROUP BY with SUM
SELECT leave_detail_id, emp_id, SUM(leave_count) FROM table GROUP BY Leave_detail_id, emp_id;
I think they want the fields in the select as well,
SELECT leave_detail_id, emp_id, SUM(leave_count) FROM table GROUP BY leave_detail_id, emp_id;

Mysql query help to get users count from table area wise

I have a table which is having some report info. In that table I have userid and areaname .
Now my requirement is to get the count of user's list based on area
For example table will have
userid | areaname
-----------------
1 |area 1
1 |area 1
2 |area2
2 |area 2
2 |area2
3 |area1
3 |area1
4 |area3
5 |area2
---------------
Result must be
area1 2users
area2 2users
area3 1user
what is the mysql query to achieve this?
Use the Aggregate function COUNT() to get the number of users and GROUP BY to get the count based on areaname
Use DISTINCT for unique values
SELECT COUNT(DISTINCT userid),areaname FROM tablename GROUP BY areaname;
SELECT count(userid),area FROM YOURTABLENAME GROUP BY area;
I see, you can have dublicate entries ad well:
So I would make a sub Select
SELECT sum(partly_sum), area
FROM (
SELECT
userid, area , count(*) as partly_sum
FROM
_YOUR_TABLE_NAME_
WHERE 1
GROUP BY area, userid
) as a_bad_sub_query
WHERE 1
GROUP BY area
Regards
You can use distinct to avoid dupe entries
SELECT COUNT(DISTINCT userid),areaname FROM tablename GROUP BY areaname

MySQL: select last (max) value from column and count of all rows

How can I select last (=max) value from column and count of all rows in single query?
ID ITEM_ID VALUE
1 1 100
2 1 101
3 2 201
4 3 333
5 2 222
6 1 111
I want to select last / max value for particular ITEM_ID and count of all rows with this ID.
For ITEM_ID = 1 thus:
VALUE COUNT
111 3
My query is like this:
SELECT (SELECT COUNT(*) FROM table) AS count, (SELECT value FROM table ORDER BY id DESC LIMIT 1) AS value FROM table WHERE item_id = 1 LIMIT 1
It works but looks ... weird. Is there any better (simpler / faster) solution? Thanks
You need to do a GROUP BY on column ITEM_ID while getting the MAX() and COUNT() like
select max(value) as `VALUE`,
count(*) as `COUNT`
from your_table
group by ITEM_ID;

PHP function to find the median of a column in MySQL

I have a database, db and in it a table, Table.
It looks somewhat like:
id | val
--------
1 | 45
2 | 35
3 | 23
4 | 49
5 | 67
6 | 12
7 | 0
8 | 87
9 | 46
(This is just an example data set. Actual data set is huge. And I need to work in least time possible.)
I need to find the median of the column val. Actually I need a php function to be used multiple times.
A similar question does exist: Simple way to calculate median with MySQL
I tried a few answers in this question, none of them worked for me. The accepted answer doesn't work since it used to work with an older version of SQL only.
PS: It should also work in the case of many duplicates.
just for fun i thought i try and do it all in MySQL, here's the sqlFiddle
SELECT
CASE
WHEN MOD((select count(*) as count from t),2)=1 THEN
(select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = CEIL((select count(*) as count from t)/2)
)
ELSE
((select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = (select count(*) as count from t)/2)+
(select val from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row = ((select count(*) as count from t)/2)+1))/2
END AS median
Just replace occurences of t with your table name, don't change t1.
Also if the table has no rows, it'll return NULL as median.
This query can be further reduced to the below (sqlFiddle)
SELECT #rowCount:=(select count(*) as count from t) AS rowcount,
(select AVG(val) from
(select #row:=#row+1 as row,val
from t,(select #row:=0)r
order by val)t1
where t1.row IN (FLOOR((#rowCount+1)/2),
CEIL((#rowCount+1)/2)
)
) as Median
It'll return 2 columns, a rowcount column and a median column. I put the rowcount column there because i didn't want to count from t multiple times like previous query.

Categories