Different people's same SSN & DL - mysql

let say we have a table with below column details.
now I wanted to extract only those custID's where either SSN or DL number is same for different custid
table
***CustID SSN DL***
1111 112331 DL1234
1112 113096 DL0987
1113 113861 DL1234
1114 112331 DL2315
1115 111104 DL5443
1115 111104 DL5443
in this I only want 1111,1113 & 1114
enter image description here

In Oracle, you can do it in a single table scan using analytic functions:
SELECT CustID
FROM (
SELECT CustID,
COUNT(*) OVER (PARTITION BY SSN, DL) AS num_ssl_dn,
COUNT(*) OVER (PARTITION BY SSN) AS num_ssn,
COUNT(*) OVER (PARTITION BY DL) AS num_dl
FROM table_name
)
WHERE num_ssn > num_ssl_dn
OR num_dl > num_ssl_dn;
Which, for the sample data:
CREATE TABLE table_name ( CustID, SSN, DL ) AS
SELECT 1111, 112331, 'DL1234' FROM DUAL UNION ALL
SELECT 1112, 113096, 'DL0987' FROM DUAL UNION ALL
SELECT 1113, 113861, 'DL1234' FROM DUAL UNION ALL
SELECT 1114, 112331, 'DL2315' FROM DUAL UNION ALL
SELECT 1115, 111104, 'DL5443' FROM DUAL UNION ALL
SELECT 1115, 111104, 'DL5443' FROM DUAL;
Outputs:
CUSTID
1111
1114
1113
sqlfiddle here

You can use exists:
select t.*
from t
where exists (select 1
from t t2
where t2.ssn = t.ssn and t2.custid <> t.custid
) or
exists (select 1
from t t2
where t2.dl = t.dl and t2.custid <> t.custid
) ;
This intentionally uses two exists instead of or in a single subquery so the optimizer can use indexes on (ssn) and (dl) if available.

Assuming the table name is table_name, you can do it like this:
select custid
from (
select custid,
count(distinct custid) over (partition by ssn) ssn_ct,
count(distinct custid) over (partition by dl) dl_ct
from table_name
)
where ssn_ct > 1 or dl_ct > 1
;

Related

How to process multiple record with same id into single record with login / logout time in SQL?

is this possible to make a "newtable" from "oldtable" like a picture down below?
Use PIVOT method :
Declare #table table (id varchar(10),[time] time)
insert into #table
SELECT '01','10:08:23'
UNION ALL
SELECT '02','10:10:50'
UNION ALL
SELECT '01','13:30:00'
SELECT *
FROM
(
SELECT id , time , CASE WHEN MIN(RNo) = 1 THEN 'CheckIn' WHEN MAX(RNo) >
1 THEN 'CheckOut' END Type
FROM
(
SELECT * , ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) RNo
FROM #table
) A
GROUP BY id , time
) A
PIVOT
(
MAX(time) FOR Type IN ([CheckIn],[CheckOut])
)Pvt
This can be use for matching column (s)
INSERT INTO `NEWTABLE`(`id`, `check in`)
SELECT o.id, o.time FROM OLDTABLE o

select query from one table to check same value exist in column, mysql select query

I have one table and i want to check that for one column all value are same.
following is the entry in my table.
two column
rid,value
(1,1)
(1,1)
(2,1)
(2,0)
(2,0)
(3,0)
(3,0)
(3,0)
I want query which gives me rid 1 because all of its value is 1. all record for rid 1 has value 1 and rid 2 and 3 does not has all value as 1 so they should not be selected.
Using group by and having can get what you want:
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( distinct value) = 1
UPDATE
According to the comment, filter the value will get the result:
SELECT *
FROM
(
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( distinct value) = 1
) AS T1
WHERE value = 1
If the values would only be 1 or 0, then you could do this trick:
SELECT rid, value
FROM my_table
GROUP BY rid
HAVING COUNT( * ) = SUM(value)
You can do like this:
CREATE TABLE my_table (
id varchar(255),
col_value varchar(255)
);
INSERT INTO my_table
VALUES
('1','1'),
('1','1'),
('2','1'),
('2','1'),
('2','1'),
('2','4'),
('3','1'),
('3','1');
Query for selection:
SELECT src.* FROM
(
SELECT DISTINCT t1.* FROM my_table AS t1
) AS src
WHERE src.id NOT IN(
SELECT test.id
FROM
(
SELECT DISTINCT t1.* FROM my_table AS t1
) AS test
GROUP BY test.id
HAVING COUNT(*) > 1
)
fiddle here.

mySQL union with calculated row

I have a query similar to this:
select 'table_1', count(*)
from table_1
union
select 'table_2', count(*)
from table_2
union
select 'table_n', count(*)
from table_n
returning the total of rows for each table (n tables).
table_1 | 100
table_2 | 150
table_n | 400
I want to know if there is a mysql function that can just add a new record at the end making the sum of all rows like this:
table_1 | 100
table_2 | 150
table_n | 400
total | 650
Is there a way to do that in mySQL (version 5.5) whithout using a procedure?
(for exemple using a variable inside the sql if supported)
select ifnull(table_name,'Total'), sum(row_count)
from (select 'table_1' table_name, count(*) row_count
from table_1
union
select 'table_2' table_name, count(*) row_count
from table_2
union
select 'table_n' table_name, count(*) row_count
from table_n ) temp
group by table_name with rollup;
Maybe use WITH ROLLUP:-
SELECT TableName, TableCount
FROM
(
SELECT 'table_1' AS TableName, COUNT(*) AS TableCount
FROM table_1
union
SELECT 'table_2' AS TableName, COUNT(*) AS TableCount
FROM table_2
SELECT
select 'table_n' AS TableName, COUNT(*) AS TableCount
FROM table_n
) Sub1
GROUP BY TableName, TableCount WITH ROLLUP
If you are only after the the number of rows, you should use the system table.
This will have the advantage that if you are preparing the query you don't have to hard code the table names as these can be passed as parameters:
select ifnull(table_name,'Total') as table_name, sum(table_rows) as table_rows
from (
SELECT
TABLE_NAME,
TABLE_ROWS
FROM
INFORMATION_SCHEMA.TABLES
WHERE
TABLE_NAME IN ('tOne', 'tTwo', 'tThree')
) temp
group by table_name with rollup;
select 'table_1', count(*)
from table_1
union
select 'table_2', count(*)
from table_2
union
select 'table_n', count(*)
from table_n
union
select 'total', sum(a.count)
from (
select 'table_1', count(*)
from table_1
union
select 'table_2', count(*)
from table_2
union
select 'table_n', count(*)
from table_n
) a

How to insert a row in mysql before union?

Say I have the following:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age FROM (
SELECT name, age FROM clubAmembers
UNION
SELECT name, age FROM clubBmembers
)
) AS atable
How can I make it such that I can "stick in a new row at the beginning of the table" prior to the SELECT union such that it would start with:
rownum | name| age
1 | "Jordan" | 6 <-- This is an arbitrarily inserted record with name="Jordan" age="6" that is not a part of any of the clubAmembers or clubBmembers table.
The rest of the table (rownum 2 and onwards) would contain the actual result form the union with clubAmembers then clubBmembers.
Basically I am looking for:
CREATE TABLE
INSERT a row "Jordan" | 6
Perform select with union such that the rows after the first would start with "rownum=2", all the data from clubAmembers, etc.
How to best do this?
"At the beginning of the table" is not truly meaningful to relational databases because the order results are returned are not guaranteed until you use an ORDER BY clause, at which point the order on disk becomes a moot point anyway.
In your case, since you want to guarantee an order in your result clause (and therefore ordering #rownum, you will have to use ORDER BY. Something like:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION
SELECT name, age, 1 AS ord FROM clubAmembers
UNION
SELECT name, age, 1 AS ord FROM clubBmembers
ORDER BY ord
)
) AS atable
Note that at no point does this guarantee that rows in clubAmembers will have a lower rownum than rows in clubBmembers. If you want to guarantee that clubAmembers have a lower rownum, while keeping the semantics of UNION (versus UNION ALL), you can use the following:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION ALL
SELECT name, age, 1 AS ord FROM clubAmembers
UNION ALL
SELECT name, age, 2 AS ord FROM clubBmembers AS b
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = b.name AND a.age = b.age)
ORDER BY ord
)
) AS atable
Note if {name, age} could be duplicated within the clubXmembers table, you will need to add DISTINCT:
...
SELECT DISTINCT name, age, 1 AS ord FROM clubAmembers
UNION ALL
...
As per the request in the comments, if you had a clubCmembers table, you would do:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age
FROM (
SELECT 'Jordan' AS name, 6 AS age, 0 AS ord
UNION ALL
SELECT name, age, 1 AS ord FROM clubAmembers
UNION ALL
SELECT name, age, 2 AS ord FROM clubBmembers AS b
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = b.name AND a.age = b.age)
SELECT name, age, 3 AS ord FROM clubCmembers AS c
WHERE NOT EXISTS(SELECT 1 FROM clubAmembers AS a
WHERE a.name = c.name AND a.age = c.age)
AND NOT EXISTS(SELECT 1 FROM clubBmembers AS b
WHERE b.name = c.name AND b.age = c.age)
ORDER BY ord
)
) AS atable
I'm not sure if I got it right. But why don't you just add another union like this:
CREATE TABLE newtable AS (
SELECT #rownum:=#rownum+1 as rownum, name, age FROM (
SELECT 1, "Jordan", 6
UNION ALL
SELECT name, age FROM clubAmembers
UNION ALL
SELECT name, age FROM clubBmembers
)
) AS atable
You can separate the create table statmenet from the insert statmenet:
Create the table (you must know which colums are gona be there)
Insert your 1st record (INSERT INTO .... Values(...))
Use your statement but with insert into instead of create table like: INSERT INTO YourNewTable.... Values(YourSubQuery) (Nr and tye of columns must match your subquery)
This should do, I believe:
CREATE TABLE newtable AS (
SELECT (#rownum:=IFNULL(#rownum,0)+1)+1 as rownum, name, age FROM (
SELECT name, age FROM clubAmembers
UNION
SELECT name, age FROM clubBmembers
) AS s
UNION ALL
SELECT 1, 'Jordan', 6
) AS atable
Demo at SQL Fiddle: http://sqlfiddle.com/#!2/ab825/6

MySQL; Get information from 3 table same time

People
here is my little problem.
I have three table:
a_names_1
b_names_2
c_names_3
they are same by structure. all of them has two item: name and used
Is there any QUERY to run to get and count all the 'name' that has 'used'=1 from all those three tables together.
I've tried this one, but didn't work:
(SELECT COUNT(*) 'name' from a_names_1) UNION
(SELECT COUNT(*) 'name' from a_names_2) UNION
(SELECT COUNT(*) 'name' from a_names_3) WHERE `used`=1
I'm using PHPMyAdmin for MySQL.
Any Help would be appreciated.. thanks in advance
This query outputs count of distinct names from all tables with used=1
select count(distinct name)
from
(
select name,used from a_names_1 where used=1
union all
select name,used from a_names_2 where used=1
union all
select name,used from a_names_3 where used=1
) t
If you need to SUM all USED for each NAME from all tables and output only with SUM of used=1 then:
select count(*) from
(
select name, SUM(used)
from
(
select name,used from a_names_1
union all
select name,used from a_names_2
union all
select name,used from a_names_3
) t
GROUP BY name
HAVING SUM(used)=1
) t1
select count(*) as name
from
(
select name, used from a_names_1
union
select name, used from a_names_2
union
select name, used from a_names_3) t
where t.used = 1
Probably this is slow, because you lose the index optimizations. What I would do is do the three queries, something like
SELECT SUM('name') AS name_sum
FROM ((SELECT COUNT(*) 'name' from a_names_1 WHERE `used`=1)
UNION (SELECT COUNT(*) 'name' from a_names_2 WHERE `used`=1));
If this doesn't work, it is probably a problem with the usage of name
Maybe you wanted this way:
select count(*) as cnt
from
(
select name from a_names_1 t1 where t1.used = 1
union
select name from a_names_2 t2 where t2.used = 1
union
select name from a_names_3 t3 where t3.used = 1
) t
The straight forward solution;
SELECT SUM(used) FROM (
SELECT used FROM a_names_1 WHERE used=1
UNION ALL
SELECT used FROM a_names_2 WHERE used=1
UNION ALL
SELECT used FROM a_names_3 WHERE used=1
) a
SQLfiddle for testing
An alternative if you have an index on used (and the only values of used are 0 or 1) is to just do the counting using the index;
SELECT SUM(used) total FROM (
SELECT SUM(used) used FROM a_names_1
UNION ALL
SELECT SUM(used) FROM a_names_2
UNION ALL
SELECT SUM(used) FROM a_names_3
) a
SQLfiddle for this example.
If you look at the query plan of the latter query, you can see it uses the indexes effectively.