mysql query group function as a column - mysql

I need to write a query to calculate the sum of each account but the special thing that I want is to group the some of the debit of each month as a column.
So what I need is like this example:
SELECT accid "Account ID", Left(tr_date,7) "Date", SUM(debit) "Debit Sum"
FROM transactions
WHERE tr_date Between "2014-07-01" and "2014-09-30"
GROUP BY acc_id, LEFT(tr_date,7);
The result will be something like that:
Account ID Date Debit Sum
1111 2014-07 300
1111 2014-08 351
1111 2014-09 352
1123 2014-07 500
1123 2014-08 100
1123 2014-09 230
But what I was asked to have is the following result:
Account ID 2014-07 2014-08 2014-09
1111 300 351 352
1123 500 100 230
where the user chooses the dates so the number of the columns is not limited
is there any way to do this or no? thank you for any comment or answer.

The only way to do that is to know the dates beforehand.
SELECT accid "Account ID"
SUM(if(LEFT(tr_date,7)="2014-07",debit,0)) "2014-07"
SUM(if(LEFT(tr_date,7)="2014-08",debit,0)) "2014-09"
SUM(if(LEFT(tr_date,7)="2014-09",debit,0)) "2014-08"
FROM transactions
WHERE tr_date Between "2014-07-01" AND "2014-09-30"
GROUP BY acc_id
if you need the user to be able to choose or add columns, you'll need to build the query dinamically either with a stored procedure or another scripting language.
PD: you're treating your dates as strings and I kept that logic. It's not a good practice though

Related

Access - Finding duplicates between 2 tables between 2 dates

I need your help in access how to count the duplicated during certain period
Table One : Unique Values
Number
Close Time
Max Date
1110
01-11-2022 8:47:00 AM
01-12-2022 8:47:00 AM
1111
02-11-2022 8:47:00 AM
02-12-2022 8:47:00 AM
1112
03-11-2022 8:47:00 AM
03-12-2022 8:47:00 AM
Table Two : Contain the unique value and duplicated Value
Number Close Time
1110 01-11-22 8:47
1110 02-11-22 8:47
1110 03-11-22 8:47
1111 02-11-22 8:47
1111 05-11-22 8:47
1111 06-12-22 8:47
1112 03-11-22 8:47
1112 08-12-22 8:47
1112 09-12-22 8:47
i need 2 types of result
first one include the value im looking for like this
Result Count
1110 3
1111 2
1112 1
and the second type exclude the value im looking for
Result Count
1110 2
1111 1
1112 0
i can do it in excel using =countifs but now im working on huge data ( millions of records ) and most of the data sent on access files
enter image description here
i dont know why tables became like this so i added a photo
Perhaps this query will suit you
SELECT t3.Num1 AS Num, sum(inResult1) AS CountInclude, sum(inResult2) AS CountExclude
FROM
(SELECT t1.Number as Num1,t1.CloseTime as CloseTime1,t1.MaxDate
,t2.Number as Num2,t2.CloseTime as CloseTime2
, iif(t2.CloseTime >= t1.CloseTime and t2.CloseTime<=t1.MaxDate,1,0) AS inResult1
, iif(t2.CloseTime > t1.CloseTime and t2.CloseTime<=t1.MaxDate,1,0) AS inResult2
FROM tableOne AS t1 INNER JOIN tableTwo AS t2 ON t1.Number = t2.Number
) AS T3
GROUP BY T3.Num1;
You may write "LEFT JOIN", this will be better.
Should be doable with a GROUP BY and COUNT(*):
SELECT Number, COUNT(*)
FROM tableTwo
GROUP BY Number, CloseTime
For the second result, just put COUNT(*)-1.

Make a query to combine one result from two different tables with same / different columns

I am trying to make single query for a single result from two different tables. This table has same columns and also different columns.
Table Deposits
Name
D_Currency
D_Amount
Datetime
Michael
USD
500
2022-12-10 09:12:45
Susan
JPY
10000
2022-12-15 12:34:11
John
KRW
7000
2022-12-13 15:21:08
Table Withdrawal
Name
W_Currency
W_Amount
Datetime
Michael
USD
500
2022-12-11 09:55:32
Susan
EUR
800
2022-12-17 11:23:45
John
USD
300
2022-12-13 13:33:43
Result I want:
Name
D_Currency
D_Amount
W_Currency
W_Amount
Datetime
Michael
USD
500
2022-12-10 09:12:45
Michael
USD
500
2022-12-11 09:55:32
John
USD
300
2022-12-13 13:33:43
John
KRW
7000
2022-12-13 15:21:08
Susan
JPY
10000
2022-12-15 12:34:11
Susan
EUR
800
2022-12-17 11:23:45
I want all the columns from both tables, but the order is in Datetime.
I think I can use column Name for join, but not sure how to add Datetime.
First I tried join, which didn't work:
SELECT d.Name, d.D_currency, d.D_amount, w.W_currency, w.W_amount,
d.Datetime as date, w.Datetime as date
FROM Deposits d
JOIN Withdrawal w on w.Name = d.Name
ORDER BY date
I was thinking of UNION, but don't have the slightest idea how to even use it.
Please help.
In order to use the UNION operation, the requirement is that you need to have the exact same schema for the two tables you're applying it on. You can use the NULL values to fill the fields whose value you don't have, and rename the field with the corresponding field name you have in the expected output table.
SELECT Name, D_Currency, D_Amount,
NULL AS W_Currency, NULL AS W_Amount,
Datetime_
FROM Deposits
UNION ALL
SELECT Name, NULL AS D_Currency, NULL AS D_Amount,
W_Currency, W_Amount,
Datetime_
FROM Withdrawal
ORDER BY Name
Some remarks to take into account when applying a union operation:
Applying the union between two sets as we know it, is carried out by the UNION ALL operation. The difference between UNION and UNION ALL is that the former applies an aggregation to eliminate the duplicates too, if you have any. Since in your case you're not supposed to have duplicates, you can avoid stacking up an unnecessary operation.
The order of the fields over the two table you're carrying the union on is important. If the two tables don't have the same fields in the same order, the DBMS will throw a schema mismatch error.
The last ORDER BY clause will apply on the whole output of the union operation.
Check the demo here.

mysql query to identify groups of data based on timestmp

I have records of smartmeter in an mysql database.
Records in timestamp order looking in generall as follow:
key
timestamp
watt now
000001
2022-10-04-01-01-01
10
000002
2022-10-04-01-02-01
10
000003
2022-10-04-01-03-01
101
000004
2022-10-04-01-04-01
101
000005
2022-10-04-01-05-01
102
000006
2022-10-04-01-06-01
101
000007
2022-10-04-01-07-01
102
000008
2022-10-04-01-08-01
10
000009
2022-10-04-01-09-01
10
000010
2022-10-04-01-09-01
10
000011
2022-10-04-01-09-01
107
000012
2022-10-04-01-09-01
101
000013
2022-10-04-01-09-01
109
000014
2022-10-04-01-09-01
10
000015
2022-10-04-01-09-01
10
I want to identify the groups with bigger number (lets say > 100)
and give them an incresing id. Also I want to get per group the first and last key id
Result of query should look like this:
month
day
numbers of group
first id
last id
average watt
10
04
0
000003
000007
102
10
04
1
000011
0000013
105
Any help apreciated
You'll need something to identify them as a group. My first thought was using RANK() or DENSE_RANK() but after multiple tries, I couldn't find a way. Then I thought about using LAG() but still I'm stuck at how to re-identify the rows as new group. After testing many times, I come up with this suggestion:
WITH cte AS (
SELECT s1.*,
#n := COALESCE(IF(s1.skey=1,1,s2.skey), #n) As newGroup
FROM smartmeter s1
LEFT JOIN (
SELECT skey,
stimestamp,
watt,
LENGTH(watt) AS lenwatt,
LAG(LENGTH(watt)) OVER (ORDER BY skey) llwatt
FROM smartmeter) s2 ON s1.skey=s2.skey
AND lenwatt != llwatt)
SELECT MONTH(stimestamp) AS Month,
DAY(stimestamp) AS Day,
ROW_NUMBER() OVER (ORDER BY MIN(skey)) AS 'numbers of group',
MIN(skey) AS 'first id',
MAX(skey) AS 'last id',
AVG(watt) AS 'Average watt',
CEIL(AVG(watt)) AS 'Average watt rounded',
newGroup
FROM cte
WHERE watt >= 100
GROUP BY newGroup, MONTH(stimestamp), DAY(stimestamp)
By the way, I've changed some of your column names because key is actually a reserve word. Although you can use it as column name as long as you wrap it in backticks, I personally find it's a hassle to do it every time.
Ok, so my idea was to use LENGTH(watt) and ORDER BY skey in the LAG() function. Then I'll separate those rows where the length doesn't match and use that as a starting point for each new group. After that, I left join the result of that with smartmeter table. The next challenge is to assign each of the rows that doesn't match with previous skey value then I've found this answer and applied it into the cte.
Once those are done, I just write another query to fulfil your expected result. Although, some part of it is not exactly as what you expected.
Here's a demo fiddle

MYSQL query - cross tab? Union? Join? Select? What should I be looking for?

Not sure what exactly it is I should be looking for, so I'm reaching out for help.
I have two tables that through queries I need to spit out one. the two tables are as follows:
Transactions:
TransactionID SiteID EmployeeName
520 2 Michael
521 3 Gene
TransactionResponse:
TransactionID PromptMessage Response PromptID
520 Enter Odometer 4500 14
520 Enter Vehicle ID 345 13
521 Enter Odometer 5427 14
521 Enter Vehicle ID 346 13
But what I need is the following, let's call it TransactionSummary:
TransactionID SiteID EmployeeName 'Odometer' 'VehicleID'
520 2 Michael 4500 345
521 3 Gene 5427 346
The "PromptID" column is the number version of "PromptMessage" so I could query off that if it's easier.
A good direction for what this query would be called is the least I'm hoping for. True extra credit for working examples or even using this provided example would be awesome!
For a predefined number of possible PromptID values you can use something like the following query:
SELECT t.TransactionID, t.SiteID, t.EmployeeName,
MAX(CASE WHEN PromptID = 13 THEN Response END) AS 'VehicleID',
MAX(CASE WHEN PromptID = 14 THEN Response END) AS 'Odometer'
FROM Transactions AS t
LEFT JOIN TransactionResponse AS tr
ON t.TransactionID = tr.TransactionID AND t.SiteID = tr.SiteID
GROUP BY t.TransactionID, t.SiteID, t.EmployeeName
The above query uses what is called conditional aggregation: a CASE expression is used within an aggregate function, so as to conditionally account for a subset of records within a group.

PHP / SQL Group Rows and Sum Columns

I have a database where I need to group users together and then sum the invoice amount into a total. I just cannot seem to figure an elegant way of doing this, I tried iterating though a while loop using each usersID via an IF statement but this method would not be practical as each new user added later would require a new if statement to be added.
SQL Example
UserID Invoice InvoiceAMT
419 1 20.00
419 2 30.99
420 3 30.00
421 4 1.00
419 5 60.00
What I want to return is
UserID Total Invoices Total Amount
419 3 110.99
420 1 30.00
421 1 1.00
Use GROUP BY with SUM()
SELECT UserID, COUNT(Invoice) `Total Invoices`, SUM(InvoiceAMT) `Total Amount`
FROM table
GROUP BY UserID
Column names with spaces are bad so avoid them. For example instead of Total Invoices you should use TotalInvoices or Total_Invoices