I have the next table with data:
user group dt_action
----- ----- ---------
John salvage 2016-3-2
Dennis fire 2016-1-1
Martha fire 2016-12-23
John rescue 2016-1-20
John salvage 2017-1-26
Developer NULL 2016-5-6
Dennis several 2016-4-29
Martha fire 2003-1-1
My idea is to group by the category "group", counting the amount of gorups per each user, but on the datetime field, I want to keep the minim date of each group sumarized. The result should be something like that:
user group count_group dt_action_min
---- ----- ----------- -------------
John salvage 2 2016-3-2
John rescue 1 2016-1-20
Dennis fire 1 2016-1-1
Dennis several 1 2016-4-29
Martha fire 2 2003-1-1
Developer NULL 1 2016-5-6
This is a query that long time ago has stolen my dream, but I can get it!
Thanks a lot,
Dani
CREATE table/INSERT data
CREATE TABLE DATA
(`user` VARCHAR(9), `group` VARCHAR(7), `dt_action` VARCHAR(10))
;
INSERT INTO DATA
(`user`, `group`, `dt_action`)
VALUES
('John', 'salvage', '2016-3-2'),
('Dennis', 'fire', '2016-1-1'),
('Martha', 'fire', '2016-12-23'),
('John', 'rescue', '2016-1-20'),
('John', 'salvage', '2017-1-26'),
('Developer', NULL, '2016-5-6'),
('Dennis', 'several', '2016-4-29'),
('Martha', 'fire', '2003-1-1')
;
Query
Replace data with your own table name
SELECT
`data`.`user`
, `data`.`group`
, `data_group`.`count_group`
, `data_group`.`min_dt_action`
FROM
`data`
INNER JOIN (
SELECT
`data`.user
, `data`.`group`
, COUNT(*) count_group
, MIN(`data`.`dt_action`) min_dt_action
FROM
`data`
GROUP BY
`data`.user
, `data`.`group`
) data_group
ON
`data`.`user` = data_group.`user`
AND
`data`.dt_action = data_group.min_dt_action
ORDER BY
`data_group`.`count_group` DESC
Result
user group count_group min_dt_action
--------- ------- ----------- ---------------
Martha fire 2 2003-1-1
John salvage 2 2016-3-2
John rescue 1 2016-1-20
Developer (NULL) 1 2016-5-6
Dennis fire 1 2016-1-1
Dennis several 1 2016-4-29
Related
Is there a way I can get specific IDs at the top, but sorted alphabetically by title, followed by the rest of the records also sorted alphabetically by title?
What I have right now:
SELECT * FROM table ORDER BY FIELD(ID,2,3) DESC, title ASC
Example:
1 Lisa
2 Hannah
3 Adam
4 Brian
Should be sorted
3 Adam (because Adam is before Hannah)
2 Hannah
4 Brian (because Brian is before Lisa)
1 Lisa
select * from table
order by
case when id in (2,3)
then 0
else 1 end asc,
title asc
You would need a use a CASE statement that generated different values for each group that you wanted and then order by the case statement and then by the name
From you smal sample data you can use a CASE WHEN and ORDER which fields should be at the start, the second order is name in my case
CREATE TABLE tab1
(`id` int, `name` varchar(6))
;
INSERT INTO tab1
(`id`, `name`)
VALUES
(1, 'Lisa'),
(2, 'Hannah'),
(3, 'Adam'),
(4, 'Brian')
;
SELECT * FROM tab1 ORDER BY
CASE WHEN FIELD(ID,2,3) THEN 1 ELSE 2 END ASC,name ASC
#, title ASC
id | name
-: | :-----
3 | Adam
2 | Hannah
4 | Brian
1 | Lisa
db<>fiddle here
It's my first time to use sql in practice, and I've met with such a situation in my .net core project:
I have a table now like this:
name:string
age:int
ticketType:enum
Jack
20
0
Anna
16
1
Tom
30
2
And I have a list of name = ["Jack", "George", "William"]
What I need is a table that contains both persons included with certain values and those excluded with default values like:
name:string
age:string
ticket:string
Jack
20 years
adult
George
Not found
Not found
William
Not found
Not found
How could I do this with sql?
Thanks in advance.
You can use a left join, but you need a list of the values you care about:
select name, t.age, t.tickettype
from (select 'Jack' as name union all
select 'George' union all
select 'William'
) n left join
t
using (name);
Note that this represents the "not found" value using NULL. This is the typical method in SQL. If you want a string, I would suggest that you do that in your application layer, because int and enum cannot represent an arbitrary string value.
The texdt you have to adapt to your needs
CREATE TABLE users
(`nameg` varchar(4), `age` int, `ticketType` int)
;
INSERT INTO users
(`nameg`, `age`, `ticketType`)
VALUES
('Jack', 20, 0),
('Anna', 16, 1),
('Tom', 30, 2)
;
SELECT t1.name,IFNULL(CONCAT (`age`, ' years'),'Not Found') age
, CASE `ticketType`WHEN
0 THen 'adult'
WHEN 1 THEn 'teenager'
WHEN 2 THEN'elserly'
ELSE 'NOT Found' END "type"
FROM (SELECT "Jack" as name UNION SELECT "George" UNION SELECT "William") t1
LEFT JOIN users u ON u.nameg = t1.name
name | age | type
:------ | :-------- | :--------
Jack | 20 years | adult
George | Not Found | NOT Found
William | Not Found | NOT Found
db<>fiddle here
I have question about querying. I need to sum total of admin per account that active / logged less than 15 days from now. The problem is one account can have many admin and on admin table have "last login" field with date.
So we want to get is all admin that not logged for less 15 days from now.. so if one of the admin logged in 15 days from now will not count...
Example:
Account Table
id | Account name
------------------
1 | Tiger company
-------------------
2 | Bear Company
Admin Table
id | Account ID | admin name | last login
-------------------------------------------
1 | 1 | Billy Tiger | 09-01-2018
2 | 1 | Shirley | 09-22-2018
3 | 2 | John Bear | 09-06-2018
4 | 2 | Kyle Bear | 09-08-2018
So based on above data if today 09-26-2018 then I need to get the total number per account and sum it that the admin per site is not or never login below 15 days from 09-26-2018 which is below 09-11-2018, so if one of the admin is logged will be not counted.
So from the example above.. what I want to get the total sum is "1" so basically per account.. hy "1" because the tiger company admin...t he "shirley" has been logged on 09-22-2018 so it's active... so not counted it and the Bear company none of the admin logged after 09-11-2018 so it count as 1...
I hope it example explains it well.. sorry for being all confusing.. is it possible to do that in one query? and like select sum(id) as 'total' ....
use sub-query , you want to filter those account who's any id login last 15 days so 1st i find those id who login with in last 15 days and filtered then count according to accountid
CREATE TABLE `Account` (
`id` int(11) PRIMARY KEY NOT NULL,
`Accountname` varchar(25) NOT NULL
);
CREATE TABLE `Admin` (
`id` int(11) PRIMARY KEY NOT NULL,
`Account_ID` int(11) NOT NULL,
`Admin_Name` varchar(25) NOT NULL,
`Last_Login` date NOT NULL
);
INSERT INTO Account
VALUES (1, 'Tiger Company'), (2, 'Bear Company');
INSERT INTO `Admin`
VALUES (1, 1, 'Billy Tiger', '2018-09-01'),
(2, 1, 'Shirley', '2018-09-22'),
(3, 2, 'John Bear', '2018-09-06'),
(4, 2, 'Kyle Bear','2018-09-08' );
select t1.Account_ID
,a1.Accountname,
count(distinct t1.Account_ID) as total from
(
select a.* from Admin a
left join
(
select distinct Account_ID from Admin
where Last_Login>=DATE_SUB(CURDATE(), INTERVAL 15 DAY)
) t on a.Account_ID=t.Account_ID
where t.Account_ID is null
) t1 join Account a1 on t1.Account_ID =a1.id group by t1.Account_ID,a1.AccountName
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=baa13620bccbf6a70f6e0fc7d6e8d199
Account_ID Accountname total
2 Bear Company 1
Easiest and probably the most efficient way at scale would be to use a JOIN between the two tables:
SELECT `account`.`id`, `account`.`Account name`, COUNT(1) as 'Active Admins'
FROM `admin`
JOIN `account` ON `account`.`id` = `admin`.`Account_ID`
WHERE `admin`.`Last_Login` >= DATE_ADD(NOW(), INTERVAL -15 DAY)
GROUP BY `account`.`id`
Result:
| id | Account name | Active Admins |
|----|---------------|---------------|
| 1 | Tiger Company | 1 |
SQL Fiddle
I have two tables:
Table 1 (customers)
customer_id customer_name salesPerson_id
1 John 1
2 Ed 1
3 Sam 2
Table 2 (customerContacts)
contact_id customer_id phone_number
1 1 687-5309
2 1 555-1234
3 1 742-1111
I am trying to let only the sales person add / update a phone number for their specific customer.
So only sales salesPerson_id 1 could update John and Ed and only salesPerson_id 2 could update Sam.
I believe I am looking for something like:
INSERT INTO customerContacts (contact_id , customer_id , phone_number) VALUES (1 , 1 , '987-6543')
ON DUPLICATE KEY UPDATE phone_number='987-6543'
IF customers.salesPerson_ID = 1
But it doesn't seem like sql supports if statements.
INSERT INTO customerContacts (contact_id , customer_id , phone_number)
Select 1 , customer_id , '987-6543'
from customers
where salesPerson_ID = 1 and customer_id=1;
This is the query which you should use in the native way but you need to fit this in your application framework
I have this sample many-to-many table for students & subjects in a university
student | subject
-----------------
James | English
James | Physics
Paul | Mathematics
Paul | English
Paul | English
Paul | French
Jake | French
Jake | Mathematics
Paul | English
I need to know the SQL query for getting the count of subjects for each student like
student | # of subjects
------------------------
James | 2
Paul | 3
Jake | 2
All you need is GROUP BY student and COUNT(DISTINCT):
SELECT student, COUNT(DISTINCT subject) AS "# of subjects"
FROM students_subjects
GROUP BY student;
You need to group
CREATE TABLE `student_subject` (
`name` varchar(256) DEFAULT NULL,
`subject` varchar(256) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `student_subject`
--
INSERT INTO `student_subject` (`name`, `subject`) VALUES
('James', 'English'),
('James', 'Physics'),
('Paul', 'Mathematics'),
('Paul', 'English'),
('Paul', 'English'),
('Paul', 'French'),
('Jake', 'Mathematics'),
('Jake', 'French');
SELECT name, COUNT(distinct subject) AS "subject_count"
FROM student_subject
GROUP BY name,subject order by name desc
#########output##############
Name subject_count
('Jake' , 2),
('James', 2),
('Paul' , 3);
SELECT student, count(*)
FROM table
GROUP BY student
You need to group the select by student:
SELECT student, count(*) as NumberOfSubjects
FROM table_name
GROUP BY student
Select student , count(subject) from Table Group by student