How to join 2 tables and order them? - mysql

I have 2 tables: _divions and _employee. In _employee there's a column division which is id_division in the table _division. I need to order them by the _division order first.
This table has a column order. I have tried this SQL statement, but it doesn't do much:
SELECT
e . *
FROM
`_employee` AS `e`
JOIN
`_division` AS d
ORDER BY
d.order,
e.division,
e.order

You missing ON clause. Try this
SELECT e.*
FROM _employee AS e
JOIN _division AS d ON d.id_division = e.division
// ^^^^ Missing
ORDER BY e.order

Below query may help. (Assuming there are divisions with no employees)
with employee as
(
select 'NISHA' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'ABC' ENAME, '10' EDIV FROM DUAL
UNION
SELECT 'DEF' ENAME, '15' EDIV FROM DUAL
UNION
SELECT 'GHI' ENAME, '20' EDIV FROM DUAL
),
DIVISION AS
(
SELECT '10' DIV_ID, 'INFO-TECH' DIV_DESC FROM DUAL
UNION
SELECT '15' DIV_ID, 'HUMAN RESOURCES' DIV_DESC FROM DUAL
UNION
SELECT '20' DIV_ID, 'SALES' DIV_DESC FROM DUAL
UNION
SELECT '25' DIV_ID, 'RESEARCH' DIV_DESC FROM DUAL
)
SELECT *
FROM EMPLOYEE, DIVISION WHERE
employee.EDIV (+) = DIVISION.DIV_ID
ORDER BY DIV_DESC, ENAME
If all employees would definitely have a division,then use employee.EDIV = DIVISION.DIV_ID instead of employee.EDIV (+) = DIVISION.DIV_ID

Related

How to update next data in mysql

create table mpr (
name nvarchar(50),
value nvarchar(50)
);
insert mpr
select 'Name','Ravi' Union all
select 'Gender','M' Union all
select 'Salary','38162' Union all
select 'Name','Sundar' Union all
select 'Gender','M' Union all
select 'Salary','34932' Union all
select 'Name','Jayesh' Union all
select 'Gender','M' Union all
select 'Salary','37224' Union all
select 'Name','Murali' Union all
select 'Gender','M' Union all
select 'Salary','43482' Union all
select 'Name','Priya' Union all
select 'Gender','F' Union all
select 'Salary','44831' Union all
select 'Name','Sandhya' Union all
select 'Gender','F' Union all
select 'Salary','26694' Union all
select 'Name','Karthik' Union all
select 'Gender','M' Union all
select 'Salary','36336' Union all
select 'Name','Premna' Union all
select 'Gender','F' Union all
select 'Salary','33432';
select * from mpr
I want output as metioned below
[enter image description here][1]
[1]: https://i.stack.imgur.com/W3amD.png
select
case when name = 'Name' then value end as 'Name',
case when name = 'Gender' then value end as 'Gender',
case when name = 'Salary' then value end as 'Salary'
from mpr
Thank you.
Your table is missing a primary key column which uniquely identifies each user. Assuming that such an id column exist, we can try a pivot query here:
SELECT id,
MAX(CASE WHEN name = 'Name' THEN value END) AS name,
MAX(CASE WHEN name = 'Gender' THEN value END) AS gender,
MAX(CASE WHEN name = 'Salary' THEN value END) AS salary
FROM mpr
GROUP BY id;

How do I fetch limited data sets for a different values on a singles column?

Suppose I've Table T and It has 3 Columns and 3rd Column contains 10 distinct values and I want to fetch 5 samples from Table T for each distinct value in column 3rd.
WITH T(A, B,C) AS(
SELECT 12,'Hi','One' FROM DUAL UNION ALL
SELECT 34,'Am','One' FROM DUAL UNION ALL
SELECT 6,'to','Two' FROM DUAL UNION ALL
SELECT 3,'do','Two' FROM DUAL UNION ALL
SELECT 5,'aim','Two' FROM DUAL UNION ALL
SELECT 6,'mine','Two' FROM DUAL UNION ALL
SELECT 4,'not','Three' FROM DUAL
)
select a,b,c from(
SELECT A,B,C,ROW_NUMBER() OVER(PARTITION BY c ORDER BY C DESC) AS R
FROM T)
where r = 1
or you could possibly try this:
SELECT MIN(T.A),
T.B,
t.c
FROM t
JOIN (SELECT C,
MAX(b) AS b
FROM T
GROUP BY C) Y ON Y.C = T.C
AND Y.B = T.B
GROUP BY t.c, t.b

Check which IDs from a set do not exists in a table

I have a list of user IDs, like this:
757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450,743799,643918,
749903,571888,30207,705953,749120,749001,749192,749978,750840,544228,702121,746246,383667,
558790,585628,592771,745818,749375,241209,749235,746860,748318,748016,748951,747321,748684,
748225,565375,748673,747869,748522,748335,744775,672229,578056,713127,740234,632608,711135,
746528,362131,742223,746567,745224,332989,439837,745418,673582,269584,742606,745135,746950,
476134,740830,742949,276934
I have a MySQL table users with the id field.
How do I check - using a query - which IDs of the ones I have do not exists in the users table?
This sounds like a simple problem to me, yet I couldn't find any example on StackOverflow which would address a fixed set of ID values.
I didn't know the find_in_set() function and took a more handcrafted approach. Not that it makes any sense given the first answer, but I'll post it anyway:
SELECT id
FROM (
SELECT '757392' AS id UNION
SELECT '733602' UNION
SELECT '749955' UNION
SELECT '744304' UNION
SELECT '746852' UNION
SELECT '753904' UNION
SELECT '755117' UNION
SELECT '636163' UNION
SELECT '564931' UNION
SELECT '740787' UNION
SELECT '751450' UNION
SELECT '743799' UNION
SELECT '643918' UNION
SELECT '749903' UNION
SELECT '571888' UNION
SELECT '30207' UNION
SELECT '705953' UNION
SELECT '749120' UNION
SELECT '749001' UNION
SELECT '749192' UNION
SELECT '749978' UNION
SELECT '750840' UNION
SELECT '544228' UNION
SELECT '702121' UNION
SELECT '746246' UNION
SELECT '383667' UNION
SELECT '558790' UNION
SELECT '585628' UNION
SELECT '592771' UNION
SELECT '745818' UNION
SELECT '749375' UNION
SELECT '241209' UNION
SELECT '749235' UNION
SELECT '746860' UNION
SELECT '748318' UNION
SELECT '748016' UNION
SELECT '748951' UNION
SELECT '747321' UNION
SELECT '748684' UNION
SELECT '748225' UNION
SELECT '565375' UNION
SELECT '748673' UNION
SELECT '747869' UNION
SELECT '748522' UNION
SELECT '748335' UNION
SELECT '744775' UNION
SELECT '672229' UNION
SELECT '578056' UNION
SELECT '713127' UNION
SELECT '740234' UNION
SELECT '632608' UNION
SELECT '711135' UNION
SELECT '746528' UNION
SELECT '362131' UNION
SELECT '742223' UNION
SELECT '746567' UNION
SELECT '745224' UNION
SELECT '332989' UNION
SELECT '439837' UNION
SELECT '745418' UNION
SELECT '673582' UNION
SELECT '269584' UNION
SELECT '742606' UNION
SELECT '745135' UNION
SELECT '746950' UNION
SELECT '476134' UNION
SELECT '740830' UNION
SELECT '742949' UNION
SELECT '276934') AS id_list
WHERE id NOT IN (
SELECT id
FROM users);
This is an option:
SELECT ids.id
FROM ( SELECT #i
, substring(#string, #start, #end-#start) id
FROM <BigTable>
, ( SELECT #string := <YourStringOfIds>
, #start:=0
, #end:=0
, #i:=0
, #len:=length(#string)
, #n:=#len-length(replace(#string,',',''))+1
) t
WHERE (#i := #i+1) <= #n
AND (#start := #end+1)
AND (#loc := locate(',',#string,#start))
AND #end := if(#loc!=0,#loc,#len+1)
) ids
LEFT JOIN <BigTable> u
ON u.id = ids.id
WHERE u.id is null
BigTable can be any table whose number of rows >= number of ids in your string.
Create temporary table, then fill it
CREATE TABLE tmp (
`id` INT NOT NULL,
PRIMARY KEY (`id`));
INSERT INTO tmp (id) VALUES (1),(2),(3),(4),(5),(6)
then make a query
SELECT tmp.id
FROM tmp
LEFT JOIN users u ON u.id = tmp.id
WHERE tmp.id IS NULL
finally drop the table
DROP TABLE tmp
You're looking for the IN clause with a negation. I.e. you can specify your list as the argument to the IN clause like so:
SELECT * FROM users
WHERE id NOT IN ( 757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450,743799,643918,749903,571888,30207,705953,749120,749001,749192,749978,750840,544228,702121,746246,383667,558790,585628,592771,745818,749375,241209,749235,746860,748318,748016,748951,747321,748684,748225,565375,748673,747869,748522,748335,744775,672229,578056,713127,740234,632608,711135,746528,362131,742223,746567,745224,332989,439837,745418,673582,269584,742606,745135,746950,476134,740830,742949,276934 );
UPDATE
My bad - I didn't read the question properly.
So the correct way would be to go with UNIONs then outer join and filter by NULL, like this:
SELECT WantedIds.id
FROM users
RIGHT JOIN (
SELECT x.id
FROM (
SELECT '757392' AS id UNION
SELECT '733602' UNION
SELECT '749955' UNION
SELECT '744304' UNION
SELECT '746852' UNION
SELECT '753904' UNION
SELECT '755117' UNION
SELECT '636163' UNION
SELECT '564931' UNION
.
.
.
) x
) WantedIds
ON WantedIds.id = users.id
WHERE users.id IS NULL
You can use MySQL's find_in_set() function to check if a value exists in a commase separated list of values:
select * from your_table
where find_in_set(field_name,'757392,733602,749955,744304,746852,753904,755117,636163,564931,740787,751450')=0

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.