MySql value and sum(value) in same row without group - mysql

I want to get the current row quantity with COUNT(*) and the total row quantity over all rows as column in every row (needed for a report trying to avoid scripting it outside the sql).
I can't use SUM(qty) because i don't want to group my result by reasons and when i use a parameter with := i only get the total qty in the last row.
My current Query looks something like
SET #sumTotal:=0;
SELECT reason, qty, (#sumTotal := #sumTotal + qty) AS total_qty
FROM
(
SELECT reason, COUNT(*) AS qty
FROM someTable
--Imagine a huge amount of joins here
GROUP BY someTableId
)base
The table someTable looks like
----------------------
projectid | reason
----------------------
1 | reason11
1 | reason12
2 | reason21
2 | reason22
2 | reason23
3 | reason31
.
.
.
3 | reason35
----------------------
The result should look something like
----------------------------
reason | qty | totalqty
----------------------------
reason1 | 2 | 10
reason2 | 3 | 10
reason3 | 5 | 10
----------------------------
Am i maybe thinking in the wrong direction and there is a easy way to fix this?

Use auxiliary SELECT query to count the number of someTable rows.
SELECT reason, qty, total_qty
FROM
(
SELECT reason, COUNT(*) AS qty
FROM someTable
GROUP BY someTableId
),
(
SELECT count(*) AS total_qty
FROM someTable
)
This produces a Cartesian product between the derived tables of subqueries. Second subquery will consist of single row with total quantity. Thus, the total quantity will be added to the first subquery.

Related

How do I count the number of rows that have different dates

I want to count the total numbers of row in SQL database.
"tableA" :
id | date |
---+------------+
1 | 2019-09-03 |
2 | 2019-09-03 |
3 | 2019-09-04 |
4 | 2019-09-05 |
I want to execute it as new column name "total" that should have like this :
total
-----
3
because they are 3 different dates.
I know that the result must use 2 query like this:
SELECT date
FROM tableA
GROUP BY date AS total;
SELECT COUNT(total)
FROM tableA;
How to combine 2 queries like that or there is another way?
Use count(distinct date)
SELECT COUNT(distinct date) FROM tableA
select count( distinct date) as total from tableA;

SQL - Multiple grouping within report

I have a table structured similarly to this:
ID
Incident_Name
Category
Source
I need a report to show all incidents grouped by category but then the amount of incidents in that category that have a certain source value.
Category | Amount | Percentage of Total | Source_1 | Source_2 | Source 3
----------------------------------------------------------------------------
Category 1 | 5 | 25% | 1 | 3 | 2
Category 2 | 15 | 75% | 10 | 2 | 3
I'm using MySQL - how would I go about doing this.
Grouping and getting the amount/percentage is fine but not sure how I'd go about doing the rest.
SELECT Category, COUNT(*) AS Amount, (COUNT(*) / (SELECT COUNT(*) FROM MyTable)) * 100 AS 'Percentage of Total',
FROM MyTable
GROUP BY Category;
Any advice
I think this is what you are trying to do.
SELECT Category,
COUNT(*) AS Amount,
(COUNT(*) / (SELECT COUNT(*) FROM MyTable)) * 100 AS 'Percentage of Total',
SUM(source=someval1) as Source_1, --this may need a change
SUM(source=someval2) as Source_2, --this may need a change
SUM(source=someval3) as Source_3 --this may need a change
FROM MyTable
GROUP BY Category;

How to select records without duplicate on just one field and duplicate field total in SQL

I have a table with 3 columns like this:
+------------+---------------+-------+
| id | category | price |
+------------+---------------+-------+
1 | Home | 20
2 | Transport | 30
3 | General | 40
4 | General | 50
My desired result is something like this:
category price
+------------+---------------+-------+
Home 20
Transport 30
General 90
I need to have category names without any duplicate. Actually I need their id and category , What is the best SQL command to make this? I used DISTINCT in the form below but I could not achieve an appropriate result.
SELECT
MIN(id) AS id, `categories`, `expenses_price`
FROM
expensess
WHERE
SUM(expenses_price)
GROUP BY `categories`
but total not calculate
Try this to get the min id and sum of prices:
SELECT
min(id) as ID, category, SUM(price)
FROM
expenses
GROUP BY category
ORDER by ID
SQLFiddle Example
It's simple group by
SELECT
min(id) id, `categories`, SUM(price) `expenses_price`
FROM
expensess
GROUP BY `categories`

select non group by columns with count in Mysql

I have a table tbl with three columns:
id | fk | dateof
1 | 1 | 2016-01-01
2 | 1 | 2016-01-02
3 | 2 | 2016-02-01
4 | 2 | 2016-03-01
5 | 3 | 2016-04-01
I want to get the results like this
Id count of Id max(dateof)
2 | 2 | 2016-01-02
4 | 2 | 2016-03-01
5 | 1 | 2016-04-01
My try
SELECT id,tbl.dateof dateof
FROM tbl
INNER JOIN
(SELECT fk, MAX(dateof) dateof ,
count(id) cnt_of_id -- How to get this count value in the result
FROM tbl
GROUP BY fk) temp
ON tbl.fk = temp.fk AND tbl.dateof = temp.dateof
This is an aggregation query, but you don't seem to want the column being aggregated. That is ok (although you cannot distinguish the rk that defines each row):
select count(*) as CountOfId, max(dateof) as maxdateof
from t
group by fk;
In other words, your subquery is pretty much all you need.
If you have a reasonable amount of data, you can use a MySQL trick:
select substring_index(group_concat(id order by dateof desc), ',', 1) as id
count(*) as CountOfId, max(dateof) as maxdateof
from t
group by fk;
Note: this is limited by the maximum intermediate size for group_concat(). This parameter can be changed and it is typically large enough for this type of query on a moderately sized table.
You obviously want one result row per fk, so group by it. Then you want the max ID, the row count and the max date for each fk:
select
max(id) as max_id,
count(*) as cnt,
max(date_of) as max_date_of
from tbl
group by fk;

MySQL conditionally populate column 3 based on DISTINCT involving 2 other columns in one table

Had a good read through similar topics but I can't quite a) find one to match my scenario, or b) understand others enough to fit / tailor / tweek to my situation.
I have a table, the important fields being;
+------+------+--------+--------+
| ID | Name | Price |Status |
+------+------+--------+--------+
| 1 | Fred | 4.50 | |
| 2 | Fred | 4.50 | |
| 3 | Fred | 5.00 | |
| 4 | John | 7.20 | |
| 5 | John | 7.20 | |
| 6 | John | 7.20 | |
| 7 | Max | 2.38 | |
| 8 | Max | 2.38 | |
| 9 | Sam | 21.00 | |
+------+------+--------+--------+
ID is an auto-incrementing value as records get added throughout the day.
NAME is a Primary Key field, which can repeat 1 to 3 times in the whole table.
Each NAME will have a PRICE value, which may or may not be the same per NAME.
There is also a STATUS field that need to be populated based on the following, which is actually the part I am stuck on.
Status = 'Y' if each DISTINCT name has only one price attached to it.
Status = 'N' if each DISTINCT name has multiple prices attached to it.
Using the table above, ID's 1, 2 and 3 should be 'N', whilst 4, 5, 6, 7, 8 and 9 should be 'Y'.
I think this may well involve some form of combination of JOINs, GROUPs, and DISTINCTs but I am at a loss on how to put that into the right order for SQL.
In order to get the count of distinct Price values per name, we must use a GROUP BY on the Name field, but since you also want to display all names ungrouped but with an additional Status field, we must first create a subselect in the FROM clause which groups by the name and determines whether the name has multiple price values or not.
When we GROUP BY Name in the subselect, COUNT(DISTINCT price) will count the number of distinct price values for each particular name. Without the DISTINCT keyword, it would simply count the number of rows where price is not null.
In conjunction with that, we use a CASE expression to insert N into the Status column if there is more than one distinct Price value for the particular name, otherwise, it will insert Y.
The subselect only returns one row per Name, so to get all names ungrouped, we join that subselect to the main table on the condition that the subselect's Name = the main table's Name:
SELECT
b.ID,
b.Name,
b.Price,
a.Status
FROM
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) a
INNER JOIN
tbl b ON a.Name = b.Name
Edit: In order to facilitate an update, you can incorporate this query using JOINs in the UPDATE like so:
UPDATE
tbl a
INNER JOIN
(
SELECT Name, CASE WHEN COUNT(DISTINCT Price) > 1 THEN 'N' ELSE 'Y' END AS Status
FROM tbl
GROUP BY Name
) b ON a.Name = b.Name
SET
a.Status = b.Status
Assuming you have an unfilled Status column in your table.
If you want to update the status column, you could do:
UPDATE mytable s
SET status = (
SELECT IF(COUNT(DISTINCT price)=1, 'Y', 'N') c
FROM (
SELECT *
FROM mytable
) s1
WHERE s1.name = s.name
GROUP BY name
);
Technically, it should not be necessary to have this:
FROM (
SELECT *
FROM mytable
) s1
but there is a mysql limitation that prevents you to select from the table you're updating. By wrapping it in parenthesis, we force mysql to create a temporary table and then it suddenly is possible.