I have a MySQL table and it has 2 columns which record users' login info:
User_id Device_id
a 123
b 123
b 321
d 321
e aaa
f ccc
g cba
h aaa
h ccc
i cba
i aaa
Now I want to add a column Group: if user_id are logined by the same group of device, then put them together. For instance, as shown below, user account a and b are logined on device 123, so a and b are in the same group. While user account b is also logined on device 321, then all accounts logined by 321 should join this group
:
User_id Device_id Group
a 123 1
b 123 1
b 321 1
d 321 1
e aaa 2
f ccc 2
g cba 2
h aaa 2
h ccc 2
i cba 2
i aaa 2
This cannot be simply dealed with group by so how to use SQL to express column Group?
You can use the below queries,
// For future insert
INSERT INTO tableName
VALUES (j, '123', CASE grouping
WHEN (SELECT count() FROM tableName tn WHERE tn.Device_id='123')=0 THEN (SELECT MAX(tn.grouping)+1 FROM tableName tn)
WHEN (SELECT count() FROM tableName tn WHERE tn.Device_id='123')>0 THEN (SELECT tn.grouping FROM tableName tn WHERE tn.Device_id='123')
END
);
//Update the existing data
UPDATE tableName
set grouping = CASE grouping
WHEN (SELECT count() FROM tableName tn WHERE tn.Device_id='123')=0 THEN (SELECT MAX(tn.grouping)+1 FROM tableName tn)
WHEN (SELECT count() FROM tableName tn WHERE tn.Device_id='123')>0 THEN (SELECT tn.grouping FROM tableName tn WHERE tn.Device_id='123')
END;
Related
I have below mentioned table:
ID Type Date Status1 Status2 Status3
1 458 2018-01-01 15:04:06 AAA A B
2 471 2017-12-31 15:04:06 AAA A B
3 458 2018-01-15 15:04:06 BBC C D
5 458 2018-01-18 15:04:06 AAA X D
There are many same value in Type column, i want to fetch the data with below mentioned condition:
Where any value in Type (should have more than one time in table) have Status1 as AAA and other rows with same value in Type are greater than Previous Date, with Status2 as C and Status3 as D together or Status3 must be D.
Output:
ID Type Date Status1 Status2 Status3
1 458 2018-01-01 15:04:06 AAA A B
3 458 2018-01-15 15:04:06 BBC C D
5 458 2018-01-18 15:04:06 AAA X D
I am using below mentioned query:
SELECT a.ID,a.Type,a.Date,b.Status1,a.Status2,a.Status3
From Table1 a
inner join Table2 b
on a.abc=b.xyz
inner join Table2 c
on a.efg=c.xyz
GROUP BY a.Type
HAVING Count(a.Type)>0
AND b.Status1='AAA'
UNION SELECT a.ID,a.Type,a.Date,b.Status1,a.Status2,a.Status3
FROM Table1 a
inner join Table2 b
on a.abc=b.xyz
inner join Table2 c
on a.efg=c.xyz
GROUP BY a.Type
HAVING Count(a.Type)>0
AND a.Date > (SELECT Date From Table1 GROUP BY Type HAVING b.Status1='AAA' AND Count(Type)>0)
AND ( Status2='A' AND Status3='D' )
OR Status3='D';
You can try something like below
SELECT t.* FROM `t` INNER JOIN
(
SELECT `type` , COUNT(`type`) ct FROM t GROUP BY `type` HAVING ct > 1
) t1
ON t1.type = t.type ORDER BY DATE ASC
I hope this will return what you want.
Try this query .
Hope this will give you the desire output .
SELECT
ID ,
Type ,
Date ,
Status1 ,
Status2 ,
Status3
FROM
[Tabel_Name]
GROUP BY
Type
HAVING
Count(Type)>0
AND
Status1='AAA'
UNION
SELECT
ID ,
Type ,
Date ,
Status1 ,
Status2 ,
Status3
FROM
[Tabel_Name]
GROUP BY
Type
HAVING
Count(Type)>0
AND
Date > (SELECT Date From [Tabel_Name] GROUP BY Type HAVING Status1='AAA' AND Count(Type)>0)
AND
( Status2='C' AND Status3='D' )
OR
Status3='D'
I need to select the rows from table "web_users" only if rows of another joined table called "web_users_branches" equals to 1.
What I have now:
SELECT id, code from web_users
JOIN
(
SELECT client_code
FROM web_users_branches
HAVING COUNT(*) = 1
) as t2
ON web_users.code = t2.client_code;
I get empty result.
Database example:
Web Users table:
id code
1 0001
2 0002
3 0003
Web Users Branches table:
id client_code
1 0001
2 0001
3 0002
4 0003
5 0003
Now after this query I should get only the user which client_code is 0002, because all the other user client_code count is not equal to 1 (there is x2 0003 and x2 0001). Any ideas?
I think you just want a group by in the subquery:
SELECT u.id, u.code
FROM web_users u JOIN
(SELECT client_code
FROM web_users_branches
GROUP BY client_code
HAVING COUNT(*) = 1
) c
ON u.code = c.client_code;
SELECT id, code
FROM web_users_branches as t1
JOIN web_users as t2
ON t2.code = t1.client_code
HAVING COUNT(*) = 1
should work. After an inner join, you only get a single row when both(!) tables have exactly one record in the beginning.
I Have a Table like this
Employeeid Name CompanyID
1 Achal 1
2 Anil 1
3 Anil 1
4 Sachi 2
5 Anil 2
6 Sachi 1
7 Sachi 2
I want to update the names of the employee if multiple employees are there in a same company
My resultant table should be like this
Employeeid Name CompanyID
1 Achal 1
2 Anil(1) 1
3 Anil(2) 1
4 Sachi(1) 2
5 Anil 2
6 Sachi 1
7 Sachi(2) 2
My query is something like this
Update tblemplayee emp
join
(
select sname,count(*)
from tblemployee
group by sname,companyid
) innertable
on innertable.employeeid=emp.employeeid
set sname = concat(sname,'(', ,')') .
How can i change my query to get the result.
If you need to execute your query only once, you could use this query:
UPDATE
employees INNER JOIN (
SELECT e1.Employeeid, COUNT(e2.Employeeid) n
FROM
employees e1 INNER JOIN employees e2
ON e1.Name=e2.Name
AND e1.CompanyID=e2.CompanyID
AND e1.Employeeid>=e2.Employeeid
INNER JOIN (SELECT Name, CompanyID
FROM employees
GROUP BY Name, CompanyID
HAVING COUNT(*)>1) dup
ON e1.Name=dup.Name AND e1.CompanyID=dup.CompanyID
GROUP BY
e1.Employeeid, e1.Name) counts
ON employees.Employeeid = counts.Employeeid
SET
Name = CONCAT(Name, '(', counts.n, ')');
Please see fiddle here.
I want to count how many times each user has rows within '5' of eachother.
For example, Don - 501 and Don - 504 should be counted, while Don - 501 and Don - 1600 should not be counted.
Start:
Name value
_________ ______________
Don 1235
Don 6012
Don 6014
Don 6300
James 9000
James 9502
James 9600
Sarah 1110
Sarah 1111
Sarah 1112
Sarah 1500
Becca 0500
Becca 0508
Becca 0709
Finish:
Name difference_5
__________ _____________
Don 1
James 0
Sarah 2
Becca 0
Use the ABS() function, in conjunction with a self-join in a subquery:
So, something like:
SELECT name, COUNT(*) / 2 AS difference_5
FROM (
SELECT a.name name, ABS(a.value - b.value)
FROM tbl a JOIN tbl b USING(name)
WHERE ABS(a.value - b.value) BETWEEN 1 AND 5
) AS t GROUP BY name
edited as per Andreas' comment.
Assuming that each name -> value pair is unique, this will get you the count of times the value is within 5 per name:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON a.name = b.name AND
a.value <> b.value AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
As you'll notice, we also have to exclude the pairs that are equal to themselves.
But if you wanted to count the number of times each name's values came within 5 of any value in the table, you can use:
SELECT a.name,
COUNT(b.name) / 2 AS difference_5
FROM tbl a
LEFT JOIN tbl b ON NOT (a.name = b.name AND a.value = b.value) AND
ABS(a.value - b.value) <= 5
GROUP BY a.name
See the SQLFiddle Demo for both solutions.
Because the OP also wants de zero counts, we'll need a self- left join. Extra logic is needed if one person has two exactly the same values, these should also be counted only once.
WITH cnts AS (
WITH pair AS (
SELECT t1.zname,t1.zvalue
FROM ztable t1
JOIN ztable t2
ON t1.zname = t2.zname
WHERE ( t1.zvalue < t2.zvalue
AND t1.zvalue >= t2.zvalue - 5 )
OR (t1.zvalue = t2.zvalue AND t1.ctid < t2.ctid)
)
SELECT DISTINCT zname
, COUNT(*) AS znumber
FROM pair
GROUP BY zname
)
, names AS (
SELECT distinct zname AS zname
FROM ztable
GROUP BY zname
)
SELECT n.zname
, COALESCE(c.znumber,0) AS znumber
FROM names n
LEFT JOIN cnts c ON n.zname = c.zname
;
RESULT:
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 14
zname | znumber
-------+---------
Sarah | 3
Don | 1
Becca | 0
James | 0
(4 rows)
NOTE: sorry for the CTE, I had not seen th mysql tag,I just liked the problem ;-)
SELECT
A.Name,
SUM(CASE WHEN (A.Value < B.Value) AND (A.Value >= B.Value - 5) THEN 1 ELSE 0 END) Difference_5
FROM
tbl A INNER JOIN
tbl B USING(Name)
GROUP BY
A.Name
I have a table such as:
id name ref_id order data_obj
-- ---- ------ ----- --------
1 Sam 0 15 [binary data]
2 Jack 0 20 [binary data]
3 Sue 0 25 [binary data]
4 Sam2 1 - [no data]
5 Sue2 3 - [no data]
6 Sam3 1 - [no data]
The idea is that I have more columns other than data_obj which can be common, so I don't want to insert them again, just want to insert a reference id to the same data.
Is it possible to write a query and select this:
1 - Sam - binary data from id 1
4 - Sam2 - binary data from id 1
6 - Sam3 - binary data from id 1
2 - Jack - binary data from id 2
3 - Sue - binary data from id 3
5 - Sue2 - binary data from id 3
Please note that I'm ordering according to column named order and there's no actual data for this column for referenced rows.
SELECT t1.id, t1.name, t2.data_obj
FROM your_table t1
LEFT JOIN your_table t2 ON t1.ref_id = t2.id
ORDER BY t1.order
Other version, which doesn't return rows without ref
SELECT t1.id, t1.name, t2.data_obj
FROM your_table t1, your_table t2
WHERE t1.ref_id = t2.id
ORDER BY t1.order
Here's a modification of #vartec's answer. This modification uses COALESCE() to combine the data_obj from either the primary row or the referenced row.
SELECT t1.id, t1.name, COALESCE(t1.data_obj, t2.data_obj)
FROM your_table t1
LEFT JOIN your_table t2 ON t1.ref_id = t2.id
ORDER BY COALESCE(t1.order, t2.order), ref_id;
COALESCE() is a standard SQL function that returns its first non-NULL argument.
Why aren't you using more than one table?
CREATE TABLE user (
user_id number not null (some form of auto increment or sequence),
name varchar(50) not null,
otherdata type,
primary key (id));
CREATE TABLE common (
common_id number not null (autoinc),
user_id number not null,
commondata type,
primary key (common_id),
unique index (user_id, common_id));
SELECT u.name, u.otherdata, c.commondata
FROM user u, common c
WHERE u.user_id = c.user_id
TABLE user
user_id name otherdata
1 Sam abc
2 Jack def
3 Sue ghi
Table common
common_id user_id commondata
1 1 AAA
2 1 BBB
3 1 CCC
4 2 DDD
5 3 EEE
6 3 FFF
Output
name otherdata commondata
Sam abc AAA
Sam abc BBB
Sam abc CCC
Jack def DDD
Sue ghi EEE
Sue ghi FFF