Group by functioning in sql [duplicate] - mysql

This question already has answers here:
MySQL - Selecting a Column not in Group By
(4 answers)
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 5 years ago.
I am running below queries on my table.
Table:
+----+-------------+--------------+----------------------------+------------+--------+
| id | Qty_holding | Qty_reserved | created | tokenid_id | uid_id |
+----+-------------+--------------+----------------------------+------------+--------+
| 1 | 10 | 0 | 2018-01-18 10:52:14.957027 | 1 | 1 |
| 2 | 20 | 0 | 2018-01-18 11:20:08.205006 | 8 | 1 |
| 3 | 110 | 0 | 2018-01-18 11:20:21.496318 | 14 | 1 |
| 4 | 10 | 0 | 2018-01-23 14:26:49.124607 | 1 | 2 |
| 5 | 3 | 0 | 2018-01-23 15:00:26.876623 | 11 | 2 |
| 6 | 7 | 0 | 2018-01-23 15:08:41.887240 | 11 | 2 |
| 7 | 11 | 0 | 2018-01-23 15:22:48.424224 | 11 | 2 |
| 8 | 15 | 0 | 2018-01-23 15:24:03.419907 | 11 | 2 |
| 9 | 19 | 0 | 2018-01-23 15:24:26.531141 | 11 | 2 |
| 10 | 23 | 0 | 2018-01-23 15:27:11.549538 | 11 | 2 |
| 11 | 27 | 0 | 2018-01-23 15:27:24.162944 | 11 | 2 |
| 12 | 7.7909428 | 0.11459088 | 2018-01-23 15:27:24.168643 | 1 | 2 |
| 13 | 3 | 0 | 2018-01-23 15:36:51.412340 | 14 | 2 |
| 14 | 7.5585988 | 0.11459088 | 2018-01-23 15:36:51.417177 | 1 | 2 |
| 15 | 6 | 0 | 2018-01-24 08:43:46.635069 | 14 | 2 |
| 16 | 7.3262548 | 0.11459088 | 2018-01-24 08:43:46.639984 | 1 | 2 |
| 17 | 9 | 0 | 2018-01-24 10:09:08.207816 | 14 | 2 |
| 18 | 7.0939108 | 0.11459088 | 2018-01-24 10:09:08.212842 | 1 | 2 |
| 19 | 6 | 3 | 2018-01-24 13:43:08.929586 | 14 | 2 |
| 20 | 3 | 6 | 2018-01-24 14:49:56.960112 | 14 | 2 |
| 21 | 0 | 9 | 2018-01-24 14:50:33.423671 | 14 | 2 |
| 22 | 30 | 9 | 2018-01-24 14:51:14.865453 | 14 | 2 |
| 23 | 4.7704708 | 0.11459088 | 2018-01-24 14:51:14.870256 | 1 | 2 |
| 24 | 27 | 12 | 2018-01-24 14:56:56.914009 | 14 | 2 |
| 25 | 24 | 15 | 2018-01-24 14:57:56.475939 | 14 | 2 |
| 26 | 21 | 15 | 2018-01-24 14:58:06.750903 | 14 | 2 |
| 27 | 18 | 15 | 2018-01-24 15:02:43.203878 | 14 | 2 |
| 28 | 4.7705074 | 0.11459088 | 2018-01-24 15:02:43.224901 | 1 | 2 |
| 29 | 24 | 0 | 2018-01-24 15:03:40.421943 | 11 | 2 |
| 30 | 4.9535074 | 0.11459088 | 2018-01-24 15:03:40.441552 | 1 | 2 |
| 31 | 1 | 0 | 2018-01-26 10:35:33.173801 | 18 | 2 |
| 32 | 10 | 15 | 2018-01-26 12:46:03.780807 | 14 | 2 |
+----+-------------+--------------+----------------------------+------------+--------+
Query 1:
select uid_id
, tokenid_id
, max(created) as max_created
from accounts_userholding
group
by uid_id
, tokenid_id
+--------+------------+----------------------------+
| uid_id | tokenid_id | max_created |
+--------+------------+----------------------------+
| 1 | 1 | 2018-01-18 10:52:14.957027 |
| 1 | 8 | 2018-01-18 11:20:08.205006 |
| 1 | 14 | 2018-01-18 11:20:21.496318 |
| 2 | 1 | 2018-01-24 15:03:40.441552 |
| 2 | 11 | 2018-01-24 15:03:40.421943 |
| 2 | 14 | 2018-01-26 12:46:03.780807 |
| 2 | 18 | 2018-01-26 10:35:33.173801 |
+--------+------------+----------------------------+
Query 2:
select uid_id
, Qty_holding
, Qty_reserved tokenid_id
, max(created) as max_created
from accounts_userholding
group
by uid_id
, tokenid_id
+--------+-------------+--------------+------------+----------------------------+
| uid_id | Qty_holding | Qty_reserved | tokenid_id | max_created |
+--------+-------------+--------------+------------+----------------------------+
| 1 | 10 | 0 | 1 | 2018-01-18 10:52:14.957027 |
| 1 | 20 | 0 | 8 | 2018-01-18 11:20:08.205006 |
| 1 | 110 | 0 | 14 | 2018-01-18 11:20:21.496318 |
| 2 | 10 | 0 | 1 | 2018-01-24 15:03:40.441552 |
| 2 | 3 | 0 | 11 | 2018-01-24 15:03:40.421943 |
| 2 | 3 | 0 | 14 | 2018-01-26 12:46:03.780807 |
| 2 | 1 | 0 | 18 | 2018-01-26 10:35:33.173801 |
+--------+-------------+--------------+------------+----------------------------+
The Qty_holding value in above is not corresponding to latest date. For instance for tokenid_id 14 and uid_id as 2 latest record is
| 32 | 10 | 15 | 2018-01-26 12:46:03.780807 | 14 | 2 |
But above query is giving qty_holding as 3.
Any insights in functioning of mysql will be helpful . Thanks!

As a rule of thumb: When you mix normal columns with aggregate functions in SELECT, you need to use GROUP BY. Do not use GROUP BY when you do not have normal columns and aggregate functions in SELECT.
The thing to put into the GROUP BY, is all from SELECT but the aggregate functions (and possible constants).
As an example if you have a query:
select a, substring(b,3), 'x', max(y)
from yourtable
You need to use GROUP BY. You leave out 'x' as it is a constant and you leave out the aggregate function. The rest goes to the GROUP BY.
select a, substring(b,3), 'x', max(y)
from yourtable
group by a, substring(b,3)
Previous MySQL versions allowed quite liberal use of GROUP BY resulting quite often just bad/incorrect code.

Related

How to compare a new value to last value in the table

I am trying to create a trigger in MySQL database. I have a table (myData) with 3 columns. Date, Values, and Status. What I am trying to achieve is, when a new value comes, if it is higher than the last value, It should insert 1 in the Status column. If it is less than the last value, It should insert 0 in the status column. I couldn't find a logic to do it. Any suggestions, please?
BEGIN
IF new.Values > // what should be here?
THEN
INSERT INTO //
END
Instead consider the following:
SELECT * FROM my_table;
+----+-------+
| id | value |
+----+-------+
| 1 | 2 |
| 2 | 12 |
| 3 | 13 |
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 7 | 8 |
| 8 | 3 |
| 9 | 10 |
| 10 | 1 |
| 11 | 18 |
| 12 | 4 |
| 13 | 6 |
| 14 | 0 |
| 15 | 2 |
| 16 | 8 |
| 17 | 14 |
| 18 | 7 |
| 19 | 15 |
| 20 | 11 |
| 21 | 12 |
| 22 | 7 |
| 23 | 20 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 28 | 12 |
| 29 | 3 |
| 30 | 18 |
| 31 | 1 |
| 32 | 12 |
+----+-------+
SELECT a.*
, b.value >= a.value n
FROM my_table a
LEFT
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id;
+----+-------+------+
| id | value | n |
+----+-------+------+
| 1 | 2 | NULL |
| 2 | 12 | 0 |
| 3 | 13 | 0 |
| 4 | 9 | 1 |
| 5 | 7 | 1 |
| 6 | 6 | 1 |
| 7 | 8 | 0 |
| 8 | 3 | 1 |
| 9 | 10 | 0 |
| 10 | 1 | 1 |
| 11 | 18 | 0 |
| 12 | 4 | 1 |
| 13 | 6 | 0 |
| 14 | 0 | 1 |
| 15 | 2 | 0 |
| 16 | 8 | 0 |
| 17 | 14 | 0 |
| 18 | 7 | 1 |
| 19 | 15 | 0 |
| 20 | 11 | 1 |
| 21 | 12 | 0 |
| 22 | 7 | 1 |
| 23 | 20 | 0 |
| 24 | 17 | 1 |
| 25 | 8 | 1 |
| 26 | 6 | 1 |
| 27 | 6 | 1 |
| 28 | 12 | 0 |
| 29 | 3 | 1 |
| 30 | 18 | 0 |
| 31 | 1 | 1 |
| 32 | 12 | 0 |
+----+-------+------+
If all you want is the rows where n=1, then the query is actually even simpler...
SELECT a.*
FROM my_table a
JOIN
( SELECT x.*
, MIN(y.id) next
FROM my_table x
LEFT
JOIN my_table y
ON y.id > x.id
GROUP
BY x.id
) b
ON b.next = a.id
AND b.value >= a.value;
+----+-------+
| id | value |
+----+-------+
| 4 | 9 |
| 5 | 7 |
| 6 | 6 |
| 8 | 3 |
| 10 | 1 |
| 12 | 4 |
| 14 | 0 |
| 18 | 7 |
| 20 | 11 |
| 22 | 7 |
| 24 | 17 |
| 25 | 8 |
| 26 | 6 |
| 27 | 6 |
| 29 | 3 |
| 31 | 1 |
+----+-------+

Calculate sum, counts in many to many

Greetings I am trying to sum up expense value for each transaction.
Association table.
**Assoc table schema**
| PK_id | FK_transaction | FK_Expense |
|-------|----------------|------------|
| 1 | 1 | 85 |
| 2 | 2 | 81 |
| 3 | 3 | 77 |
| 4 | 4 | 83 |
| 5 | 5 | 84 |
| 6 | 6 | 105 |
| 7 | 7 | 104 |
| 8 | 8 | 71 |
| 9 | 8 | 88 |
| 10 | 8 | 90 |
Transaction table
**Transaction table schema**
| PK_id | type | value | confirmed_value |
|-------|------|-------|--------------------|
| 1 | 1 | 3.2 | 0 |
| 2 | 1 | 23.2 | 0 |
| 3 | 1 | 33.2 | 0 |
| 4 | 1 | 43.2 | 11.00 |
| 5 | 1 | 53.2 | 0 |
| 6 | 1 | 63.2 | 0 |
| 7 | 1 | 73.2 | 0 |
| 8 | 1 | 83.2 | 66.00 |
| 9 | 1 | 93.2 | 0 |
| 10 | 1 | 133.2 | 77.00 |
| 11 | 1 | 123.2 | 0 |
Expences Table
| PK_id | value |
|-------|-------|
| 85 | 3.2 |
| 81 | 23.2 |
| 77 | 33.2 |
| 83 | 43.2 |
| 84 | 53.2 |
| 105 | 63.2 |
| 104 | 73.2 |
| 71 | 83.2 |
| 88 | 93.2 |
| 90 | 133.2 |
Result ::
| PK_id | value | confirmed_value |
|-------|-------|-----------------|
| 1 | 3.2 | 0 |
| 2 | 23.2 | 0 |
| 3 | 33.2 | 0 |
| 4 | 43.2 | 11 |
| 5 | 53.2 | 0 |
| 6 | 63.2 | 0 |
| 7 | 73.2 | 0 |
| 8 | 83.2 | 66 |
| 8 | 93.2 | 66 |
| 8 | 133.2 | 66 |
Desired - before calculations ( just to give u the idea )
| PK_id | value | confirmed_value |
|-------|-------|-----------------|
| 1 | 3.2 | 0 |
| 2 | 23.2 | 0 |
| 3 | 33.2 | 0 |
| 4 | 43.2 | 11 |
| 5 | 53.2 | 0 |
| 6 | 63.2 | 0 |
| 7 | 73.2 | 0 |
| 8 | 309.6 | 66 |
Full desired result
count matching values COUNT(confirmed_value = value )
count entries that not match COUNT(confirmed_value != value )
/\ Calculate value of confirmed values
?? sum(transactions.confirmed_value)
and calculate value itself
Should be a row result ( example )
=======================================================================================================================
MATCHED | NOT_MATCHED | SUM(of values) | COUNT(of confirmed equal to value ) | COUNT(of confirmed ! equal to value )
=======================================================================================================================
1 | 10 | 3003.22 | 3 | 10
=======================================================================================================================
SQL Fiddle : http://sqlfiddle.com/#!9/2ab102/9
Thanks for any tips
Try this query -
SELECT transactions.PK_id,
SUM(expenses.value),
transactions.confirmed_value
FROM `assoc`
JOIN `expenses` ON `assoc`.`FK_Expense` = `expenses`.`PK_id`
JOIN `transactions` ON `assoc`.`FK_transaction` = `transactions`.`PK_id`
GROUP BY transactions.PK_id,
transactions.confirmed_value
Fiddle Demo - http://sqlfiddle.com/#!9/2ab102/14

MySQL generate all possible combinations from numbers with a certain length

how to generate all possible combinations from numbers in a MySql table with a certain length? For example 8 numbers.
Only with MySql not together with php.
My table "numbers" contains:
0
1
2
3
4
5
6
7
8
9
I want now to let create all possible combinations in "numbers1".
Like:
00000001
00000002
00000003
00000004
It sounds like you want a cartesian product but I don't get why you want a single column in your output but anyway
select distinct case when u1.id >= u.id then u.id else u1.id end umin,
case when u1.id < u.id then u.id else u1.id end umax
from users u cross join users u1
where u1.id <> u.id
order by umin,umax
The cross join creates the cartesian product the where clause drops those where the combination/permuatation results in the same value eg 1,1 2,2 etc and the distinct dedupes
So given this
MariaDB [sandbox]> select id from users;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 6 |
| 7 |
| 8 |
| 10 |
| 12 |
| 14 |
| 15 |
| 16 |
| 17 |
| 18 |
| 19 |
| 20 |
+----+
15 rows in set (0.00 sec)
The query results in
+------+------+
| umin | umax |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 1 | 6 |
| 1 | 7 |
| 1 | 8 |
| 1 | 10 |
| 1 | 12 |
| 1 | 14 |
| 1 | 15 |
| 1 | 16 |
| 1 | 17 |
| 1 | 18 |
| 1 | 19 |
| 1 | 20 |
| 2 | 3 |
| 2 | 6 |
| 2 | 7 |
| 2 | 8 |
| 2 | 10 |
| 2 | 12 |
| 2 | 14 |
| 2 | 15 |
| 2 | 16 |
| 2 | 17 |
| 2 | 18 |
| 2 | 19 |
| 2 | 20 |
| 3 | 6 |
| 3 | 7 |
| 3 | 8 |
| 3 | 10 |
| 3 | 12 |
| 3 | 14 |
| 3 | 15 |
| 3 | 16 |
| 3 | 17 |
| 3 | 18 |
| 3 | 19 |
| 3 | 20 |
| 6 | 7 |
| 6 | 8 |
| 6 | 10 |
| 6 | 12 |
| 6 | 14 |
| 6 | 15 |
| 6 | 16 |
| 6 | 17 |
| 6 | 18 |
| 6 | 19 |
| 6 | 20 |
| 7 | 8 |
| 7 | 10 |
| 7 | 12 |
| 7 | 14 |
| 7 | 15 |
| 7 | 16 |
| 7 | 17 |
| 7 | 18 |
| 7 | 19 |
| 7 | 20 |
| 8 | 10 |
| 8 | 12 |
| 8 | 14 |
| 8 | 15 |
| 8 | 16 |
| 8 | 17 |
| 8 | 18 |
| 8 | 19 |
| 8 | 20 |
| 10 | 12 |
| 10 | 14 |
| 10 | 15 |
| 10 | 16 |
| 10 | 17 |
| 10 | 18 |
| 10 | 19 |
| 10 | 20 |
| 12 | 14 |
| 12 | 15 |
| 12 | 16 |
| 12 | 17 |
| 12 | 18 |
| 12 | 19 |
| 12 | 20 |
| 14 | 15 |
| 14 | 16 |
| 14 | 17 |
| 14 | 18 |
| 14 | 19 |
| 14 | 20 |
| 15 | 16 |
| 15 | 17 |
| 15 | 18 |
| 15 | 19 |
| 15 | 20 |
| 16 | 17 |
| 16 | 18 |
| 16 | 19 |
| 16 | 20 |
| 17 | 18 |
| 17 | 19 |
| 17 | 20 |
| 18 | 19 |
| 18 | 20 |
| 19 | 20 |
+------+------+
105 rows in set (0.00 sec)
if the length is fixed it is quite simple, so you could do something like this
DECLARE #number TABLE (num NVARCHAR(1))
INSERT INTO #number
VALUES ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9')
SELECT n1.num + n2.num + n3.num + n4.num
FROM #number n1, #number n2, #number n3, #number n4
if the number is variable you could either build the sql-command and execute it using sp_execute #cmd or you can create a table-value-function for it.
Edit: I just overread the "mysql"-part. the solution above is coded in TSQL (using MS SqlServer). I am not completely sure, but the only thing you have to change should be the declaration of the variable.
CREATE TEMPORARY TABLE #number (num NVARCHAR(1))
And if I am not mistaken instead of using sp_executeto execute a command you can use something like
PREPARE cmd FROM 'SELECT ...'
EXECUTE cmd

how to store multiple id in multiple column

first table :
table Name : ssc_course;
+---------------+-----------------+------------+
| ssc_course_id | ssc_course_name | qualify_id |
+---------------+-----------------+------------+
| 1 | HSC | 1 |
| 2 | Diploma | 1 |
| 3 | ITI | 1 |
+---------------+-----------------+------------+
second table :
table name :ssc_stream
+---------------+--------------------+-----------------+
| ssc_stream_id | ssc_stream_name | ssc_course_id(fk) |
+---------------+--------------------+-----------------+
| 1 | Science | 1 |
| 2 | Commers | 1 |
| 3 | Arts | 1 |
| 17 | Computer Engg | 2 |
| 18 | Mechanical Engg | 2 |
| 19 | Civil Engg | 2 |
| 20 | Electronics & TELE | 2 |
| 21 | E&TC | 2 |
+---------------+--------------------+-----------------+
third table :(master table)
table name : ssc_college
+------------+--------------+---------------+---------------+-
| ssc_clg_id | clg_login_id | ssc_stream_id | ssc_course_id |
+------------+--------------+---------------+---------------+-
| 9 | 2 | 1 | 1 |
| 10 | 2 | 1 | 1 |
| 11 | 2 | 2 | 1 |
| 12 | 2 | 2 | 1 |
| 13 | 2 | 3 | 1 |
| 14 | 2 | 3 | 1 |
| 15 | 3 | 1 | 1 |
| 16 | 3 | 1 | 1 |
| 17 | 3 | 2 | 1 |
| 18 | 3 | 2 | 1 |
| 19 | 3 | 3 | 1 |
| 20 | 3 | 3 | 1 |
| 21 | 4 | 1 | 1 |
| 22 | 4 | 1 | 1 |
| 23 | 4 | 2 | 1 |
| 24 | 4 | 2 | 1 |
| 25 | 4 | 3 | 1 |
| 26 | 4 | 3 | 1 |
| 27 | 5 | 17 | 2 |
| 28 | 5 | 17 | 2 |
| 29 | 5 | 18 | 2 |
| 30 | 5 | 18 | 2 |
| 31 | 5 | 19 | 2 |
| 32 | 5 | 19 | 2 |
| 33 | 5 | 20 | 2 |
| 34 | 5 | 20 | 2 |
| 35 | 5 | 21 | 2 |
| 36 | 5 | 21 | 2 |
| 38 | 6 | 17 | 2 |
| 39 | 6 | 17 | 2 |
| 40 | 6 | 18 | 2 |
*************************************************************
I am trying to save course,stream id's into ssc_college table.
1 course have multiple stream how can i insert this type of values
ex. course 1-diploma and this course have multiple stream like-
1.comp. engg , 2.mechanical ,3.e&tc i want to add course id and
stream id at a time of third (ssc_college) table.
and multiple stream for multiple course how i can add at a time
multiple parent and multiple child id in mysql table.
Note: stream are dependant of course table.

Date less than MySQL query not working

I've a table
| adsid | user_id | earned_points | redeem_points | dialer_point | app_point | date |
+-------+---------+---------------+---------------+--------------+-----------+---------------------+
| 1 | 1 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 1 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 1 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 2 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 2 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 2 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 3 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 3 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 3 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 4 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 4 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 4 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 5 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 5 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 5 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 6 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 6 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 6 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 7 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 7 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 7 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 1 | 8 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 3 | 8 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
| 2 | 8 | 25 | 15 | 23 | 2 | 2015-03-15 19:38:43 |
+-------+---------+---------------+---------------+--------------+-----------+---------------------+
The following less than date query does not works
select * from USER_POINTS_MAPPING where 'date' < '2015-03-17';
But when I do
select * from USER_POINTS_MAPPING where 'date' > '2015-03-17';
It throws back all the rows. What is this happening?
Try without ' characters (single quotation mark) around date. In MySQL either don't use any quotation mark or use this one ` (backtick) around field names.
'date' means date as string. And 'date' is always greater than '2015-03-17' when they are compared as string
While
`date`
means date as a field name
So the correct query is:
select * from USER_POINTS_MAPPING where date < '2015-03-17';
Pro tip: Don't use date as a column name. It's a reserved word. If you must use it surround it with backticks, not quotes.
where `data` < '2015-03-17'