Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I want to create a view of my database. \in fact, my database contains around 20 tables and i want to join the tables based on the foreign keys but there are some duplicates columns. Is there an easy and fast way to do it ?
Here's something that might help. You'll have to list out the columns if you do not want the dupes. You can run
SQL Fiddle Example
select group_concat(concat(table_name,'.', column_name) separator ', ')
from information_schema.columns
where table_name in ('Students', 'ClassRoster');
This will list [table_name].[column_name] for all the columns in the tables you specify in one long string. You can then copy the result and paste it next to the SELECT in your query and remove all the dupe columns if you know them. This query will show columns where there is more than one and show the table as well.
select table_name, column_name
from INFORMATION_SCHEMA.COLUMNS
where column_name in (
select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS
group by COLUMN_NAME
having count(1) > 1)
order by column_name
It still is manual but will save you some time. With a little more effort you could tweak the queries to where the whole process is just one query and not manually remove anything.
Just determined which columns you need in your view and use AS to assign a specific name to all of them.
This is an example. Both table have col1 and col2 :
SQL Fiddle
MySQL 5.5.32 Schema Setup:
CREATE TABLE Table1
(`Id` int, `Col1` varchar(1), `Col2` varchar(1), `Id2` int)
;
INSERT INTO Table1
(`Id`, `Col1`, `Col2`, `Id2`)
VALUES
(1, 'A', 'B', 1),
(2, 'B', 'C', 2),
(3, 'D', 'E', 3)
;
CREATE TABLE Table2
(`Id` int, `Col1` varchar(1), `Col2` varchar(1))
;
INSERT INTO Table2
(`Id`, `Col1`, `Col2`)
VALUES
(1, 'A', 'B'),
(2, 'B', 'C'),
(3, 'D', 'E')
;
Query 1:
SELECT Table1.Id as ID,
Table1.Col1 as COL1,
Table1.Col2 as COL2,
Table2.Col1 as COL3,
Table2.Col2 as COL4
FROM Table1
INNER JOIN Table2 ON Table1.Id2 = Table2.Id
Results:
| ID | COL1 | COL2 | COL3 | COL4 |
|----|------|------|------|------|
| 1 | A | B | A | B |
| 2 | B | C | B | C |
| 3 | D | E | D | E |
You Should Use Alias in joining like this...
Select E.Name , U.Name,E.Age,U.Age
From
TblEmployee E
inner join
TblUser U on E.EmployeeId = U.EmployeeId
Note : The above Query is only a Example So that you can go ahead
Edit: you can also do your column name what you want like this
Select E.* , U.*, E.Age as Employee Age ,U.Age as UserAge
/* you can specify some column by E.Name and if you do not want then simplye do E.* by doing thing every column of your that table will be selected */
From TblEmployee E
inner join
TblUser U on E.EmployeeId = U.EmployeeId
Related
I have 2 table and second table use relationship
table1
id name
---------
1 alpha
2 beta
table2
id name relation
-------------------
1 2015 2
2 2016 2
3 2017 2
4 2018 2
I want to see
name data
-------------------------
beta 2015,2016,2017,2018
alpha NULL
I tried the following sql query but the output is not what I wanted
I use:
SELECT
t1.name,
GROUP_CONCAT(t2.name SEPARATOR ',')
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t2.relation = t1.id
Output:
alpha 2015,2016,2017,2018
Alpha doesn't get any value in the other related tablature. the values in the output belong to the beta.
You need GROUP BY:
SELECT t1.name,
GROUP_CONCAT(t2.name SEPARATOR ',')
FROM table1 t1 LEFT JOIN
table2 t2
ON t2.relation = t1.id
GROUP BY t1.name;
In most databases (and recent versions of MySQL), your query would fail. It is an aggregation query (because of the GROUP_CONCAT()). But, t1.name is not an argument to an aggregation function and it is not a GROUP BY key.
MySQL does allow this type of query. It returns exactly one row. The value of t1.name on the one row in the result set comes from an arbitrary row.
No FKs for fiddle:
CREATE TABLE Table1 (`id` int, `name` varchar(5)) ;
INSERT INTO Table1
(`id`, `name`)
VALUES
(1, 'alpha'),
(2, 'beta')
;
CREATE TABLE Table2 (`id` int, `name` int, `relation` int);
INSERT INTO Table2
(`id`, `name`, `relation`)
VALUES
(1, 2015, 2),
(2, 2016, 2),
(3, 2017, 2),
(4, 2018, 2)
;
Statement:
SELECT
t1.name,
GROUP_CONCAT(t2.name SEPARATOR ',') -- missing an AS .... => ugly name from fiddle
FROM table1 AS t1
LEFT JOIN table2 AS t2
ON t2.relation = t1.id
group by t1.name
Output:
name GROUP_CONCAT(t2.name SEPARATOR ',')
alpha (null)
beta 2017,2018,2015,2016
So I have a join query that produces the results I want but it also inculded repeating data that I don't want.
Here is the commands
SELECT cust_id, cust_fname, cust_lname, street_address, apt, city, state, zip, h_phone, m_phone, o_phone, cu_o.order_id, order_date, s_notes, donut_id, donut_name, donut_des, donut_cost, li.donut_qty
FROM customer cu
RIGHT JOIN cust_order cu_o
ON cu.cust_id = cu_o.co_cust_id
JOIN line_item li
ON li.li_order_id = cu_o.order_id
JOIN donut
ON li.li_donut_id = donut.donut_id
;
And this is the output
Although I believe that this is not SQL's job to do this, I learned in another thread (sadly I cannot remember which one) that it can indeed be done with use of parameters. Here is a minimal and verifiable example (with a demo here):
EDIT
I realised that the original answer was missing the proper ordering of the result, so the statement is a bit more involved (you must have ordered your result set first before applying the parameter trick).
drop table if exists t;
drop table if exists u;
create table t (id int, name varchar(10));
create table u (id int, tid int, val varchar(10));
insert t values (1, 'A'), (2, 'B'), (3, 'C');
insert u values (1, 1, 'x'), (2, 1, 'y'), (3, 2, 'z'), (4,2,'w'),(5,3,'q');
select x.name, x.val from (
select o.id, case when o.name <> #test then o.name else '' end as name,
#test:=o.name, o.val
from (select t.id, t.name, u.val from u join t on u.tid = t.id order by t.name) o
join (select #test:='') test
) x
order by x.id
This is the output for this example:
+-----+----+
|name | val|
+-----+----+
|A | x |
| | y |
|B | z |
| | w |
|C | q |
+-----+----+
Then don't show it to the customer.
It is totally up to you what's gonna get out, isn't it?
I don't really see what's the problem there.
And that's the way relational databases work, if you don't like it THAT much - then you may opt out for other DB types/paradigms.
PS And, well, basically there are ways to have it the way you like it.
Say, do two queries instead of one.
Or use GPOUP_CONCAT as an aggregator function (means, along with GROUP BY) to stick that donuts together for each customer.
But these are ugly & unproductive ways.
I have the following question.
I have to columns and I want for each unique entry the first column the most frequent element of the second column. An Example would be:
COL A COL B
1 a
2 c
2 c
1 a
1 b
2 d
The query should output:
Col A COL B
1 a
2 c
Given this sample data:
CREATE TABLE t
(`a` int, `b` varchar(1))
;
INSERT INTO t
(`a`, `b`)
VALUES
(1, 'a'),
(2, 'c'),
(2, 'c'),
(1, 'a'),
(1, 'b'),
(2, 'd')
;
you first have to get the count for each with a query like this:
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
Then you can use this query as a subquery to get the rows where a certain column holds the maximum. There's a nice article about this in the manual: The Rows Holding the Group-wise Maximum of a Certain Column
Choosing for example the last method described in said article, your final query would be this:
SELECT sq1.a, sq1.b FROM
(
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
) sq1
LEFT JOIN
(
SELECT
a, b,
COUNT(*) AS amount
FROM
t
GROUP BY
a, b
) sq2 ON sq1.a = sq2.a AND sq1.amount < sq2.amount
WHERE sq2.amount IS NULL;
With this result:
+------+------+
| a | b |
+------+------+
| 1 | a |
| 2 | c |
+------+------+
Using a subselect in the SELECT clause is a simple way to solve your problem:
SELECT ColA, (SELECT ColB
FROM yourtable i
WHERE i.ColA = o.ColA
GROUP BY ColB
ORDER BY COUNT(*) DESC
LIMIT 1) AS ColB
FROM yourtable o
GROUP BY ColA;
o is just an alias for the outer query, i for the inner query. They're needed for the WHERE clause to work.
The above query is a result of the following query to find the most common occurence of ColB with a given ColA:
SELECT ColB
FROM yourtable
WHERE ColA = 1 -- Replace 1; this is where the magic happens in the above query
GROUP BY ColB
ORDER BY COUNT(*) DESC
LIMIT 1
you have to create My Sql function for this let say you function name is getMaxOccr so it will look like
CREATE FUNCTION `getMaxOccr`(val INT)
RETURNS varchar(25) CHARSET latin1
BEGIN
DECLARE answer VARCHAR(25) DEFAULT '';
SELECT colb FROM `tablename`
WHERE cola = val
ORDER BY COUNT(colb)
DESC INTO answer;
RETURN answer;
END
Once this function is created than you simply have to call
SELECT cola,getMaxOccr(cola) from tablename GROUP BY cola
this will give you the list with what you are looking for hope this helps
I have 4 tables each with different columns but they all have one column in common. This is an integer identifier column. So I will have some integer x, and I want all the rows from all 4 tables that have this one id column equal to x.
I've tried something similar to:
SELECT table1.col1, table2.col2 FROM table1 LEFT JOIN table2 ON table1.id=x OR coastlinessports.id=x
And I get back rows which have both the columns from both tables in the same row.
So one result block would have:
table1.col1, table2.col2
But I really want:
table1.col1
tale2.col2
Is there a way I can do this without doing 4 select queries in a row?
If you want sequential rows from different tables, and for each table to return a different number of rows, then you can use UNION. However, UNION requires each SELECT to return the same number of columns, so you will need to fill in the missing columns with a value (or NULL), like this:
DROP TABLE IF EXISTS `table1`;
DROP TABLE IF EXISTS `table2`;
CREATE TABLE `table1` (
`id` int(11) NOT NULL auto_increment,
`col1` VARCHAR(255),
`col2` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `table2` (
`id` int(11) NOT NULL auto_increment,
`col1` VARCHAR(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
INSERT INTO `table1` VALUES
(1, '1,1', '1,2'),
(2, '2,1', '2,2');
INSERT INTO `table2` VALUES
(1, '1,1'),
(2, '2,1');
SELECT `id`, `col1`, `col2` FROM `table1` WHERE `id` = 1
UNION
SELECT `id`, `col1`, NULL AS `col2` FROM `table2` WHERE `id` = 1;
+----+------+------+
| id | col1 | col2 |
+----+------+------+
| 1 | 1,1 | 1,2 |
| 1 | 1,1 | NULL |
+----+------+------+
If you want to further process the UNION result set, you can wrap it in another SELECT, like this:
SELECT `col1`, `col2` FROM (
SELECT `id`, `col1`, `col2` FROM `table1` WHERE `id` = 1
UNION
SELECT `id`, `col1`, NULL AS `col2` FROM `table2` WHERE `id` = 1
) AS `t1`
ORDER BY col2;
+------+------+
| col1 | col2 |
+------+------+
| 1,1 | NULL |
| 1,1 | 1,2 |
+------+------+
Is that what you are after?
This probably won't answer your question, but there's something weird about the JOIN.
Usually the "ON" condition refers to both tables being joined, similar to this:
... FROM table1 LEFT JOIN table2 ON table1.id = table2.id ...
I guess there can be cases where you wouldn't do that, but I can't think of any.
You should check out this post. It seems like what you are asking for:
http://ask.sqlteam.com/questions/870/pivoting-multiple-rows-into-one-row-with-multiple-columns
If the table is called the same you can use USING
And for the part of the given value, use WHERE
select * from table1 join table2 using(commonColumn) join table3 using(commonColumn) join table4 using(commonColumn) where commonColumn="desiredValue"
Update: on a second read of your question
You want this?
All rows of table1 where commonColumn="desiredValue"
Followed by
All rows of table2 where commonColumn="desiredValue"
Followed by
All rows of table3 where commonColumn="desiredValue"
Followed by
All rows of table4 where commonColumn="desiredValue"
If that's so, you need to use a UNION (and you have to make 4 selects)
IF the number of columns differs, you need to fill the gaps whit aliases
SELECT col1, col2, col3, col4 from table1 where commonColumn="desiredValue"
UNION
SELECT col1, col2, 0 as col3, 0 as col4 from table2 where commonColumn="desiredValue"
...
I need to implement the following query in MySQL.
(select * from emovis_reporting where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') )
intersect
( select * from emovis_reporting where (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
I know that intersect is not in MySQL. So I need another way.
Please guide me.
Microsoft SQL Server's INTERSECT "returns any distinct values that are returned by both the query on the left and right sides of the INTERSECT operand" This is different from a standard INNER JOIN or WHERE EXISTS query.
SQL Server
CREATE TABLE table_a (
id INT PRIMARY KEY,
value VARCHAR(255)
);
CREATE TABLE table_b (
id INT PRIMARY KEY,
value VARCHAR(255)
);
INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B');
INSERT INTO table_b VALUES (1, 'B');
SELECT value FROM table_a
INTERSECT
SELECT value FROM table_b
value
-----
B
(1 rows affected)
MySQL
CREATE TABLE `table_a` (
`id` INT NOT NULL AUTO_INCREMENT,
`value` varchar(255),
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
CREATE TABLE `table_b` LIKE `table_a`;
INSERT INTO table_a VALUES (1, 'A'), (2, 'B'), (3, 'B');
INSERT INTO table_b VALUES (1, 'B');
SELECT value FROM table_a
INNER JOIN table_b
USING (value);
+-------+
| value |
+-------+
| B |
| B |
+-------+
2 rows in set (0.00 sec)
SELECT value FROM table_a
WHERE (value) IN
(SELECT value FROM table_b);
+-------+
| value |
+-------+
| B |
| B |
+-------+
With this particular question, the id column is involved, so duplicate values will not be returned, but for the sake of completeness, here's a MySQL alternative using INNER JOIN and DISTINCT:
SELECT DISTINCT value FROM table_a
INNER JOIN table_b
USING (value);
+-------+
| value |
+-------+
| B |
+-------+
And another example using WHERE ... IN and DISTINCT:
SELECT DISTINCT value FROM table_a
WHERE (value) IN
(SELECT value FROM table_b);
+-------+
| value |
+-------+
| B |
+-------+
There is a more effective way of generating an intersect, by using UNION ALL and GROUP BY. Performances are twice better according to my tests on large datasets.
Example:
SELECT t1.value from (
(SELECT DISTINCT value FROM table_a)
UNION ALL
(SELECT DISTINCT value FROM table_b)
) AS t1 GROUP BY value HAVING count(*) >= 2;
It is more effective, because with the INNER JOIN solution, MySQL will look up for the results of the first query, then for each row, look up for the result in the second query. With the UNION ALL-GROUP BY solution, it will query results of the first query, results of the second query, then group the results all together at once.
Your query would always return an empty recordset since cut_name= '全プロセス' and cut_name='恐慌' will never evaluate to true.
In general, INTERSECT in MySQL should be emulated like this:
SELECT *
FROM mytable m
WHERE EXISTS
(
SELECT NULL
FROM othertable o
WHERE (o.col1 = m.col1 OR (m.col1 IS NULL AND o.col1 IS NULL))
AND (o.col2 = m.col2 OR (m.col2 IS NULL AND o.col2 IS NULL))
AND (o.col3 = m.col3 OR (m.col3 IS NULL AND o.col3 IS NULL))
)
If both your tables have columns marked as NOT NULL, you can omit the IS NULL parts and rewrite the query with a slightly more efficient IN:
SELECT *
FROM mytable m
WHERE (col1, col2, col3) IN
(
SELECT col1, col2, col3
FROM othertable o
)
I just checked it in MySQL 5.7 and am really surprised how no one offered a simple answer: NATURAL JOIN
When the tables or (select outcome) have IDENTICAL columns, you can use NATURAL JOIN as a way to find intersection:
For example:
table1:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
'4', 'Bill', '6'
table2:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
'4', 'Bill', '5'
'5', 'Max', '6'
And here is the query:
SELECT * FROM table1 NATURAL JOIN table2;
Query Result:
id, name, jobid
'1', 'John', '1'
'2', 'Jack', '3'
'3', 'Adam', '2'
For completeness here is another method for emulating INTERSECT. Note that the IN (SELECT ...) form suggested in other answers is generally more efficient.
Generally for a table called mytable with a primary key called id:
SELECT id
FROM mytable AS a
INNER JOIN mytable AS b ON a.id = b.id
WHERE
(a.col1 = "someval")
AND
(b.col1 = "someotherval")
(Note that if you use SELECT * with this query you will get twice as many columns as are defined in mytable, this is because INNER JOIN generates a Cartesian product)
The INNER JOIN here generates every permutation of row-pairs from your table. That means every combination of rows is generated, in every possible order. The WHERE clause then filters the a side of the pair, then the b side. The result is that only rows which satisfy both conditions are returned, just like intersection two queries would do.
Starting from MySQL 8.0.31 the INTERSECT is natively supported.
INTERSECT Clause:
SELECT ...
INTERSECT [ALL | DISTINCT] SELECT ...
[INTERSECT [ALL | DISTINCT] SELECT ...]
INTERSECT limits the result from multiple SELECT statements to those rows which are common to all.
Sample:
SELECT 1 AS col
INTERSECT
SELECT 1 AS col;
-- output
1
Break your problem in 2 statements: firstly, you want to select all if
(id=3 and cut_name= '全プロセス' and cut_name='恐慌')
is true . Secondly, you want to select all if
(id=3) and ( cut_name='全プロセス' or cut_name='恐慌')
is true. So, we will join both by OR because we want to select all if anyone of them is true.
select * from emovis_reporting
where (id=3 and cut_name= '全プロセス' and cut_name='恐慌') OR
( (id=3) and ( cut_name='全プロセス' or cut_name='恐慌') )
AFAIR, MySQL implements INTERSECT through INNER JOIN.
SELECT
campo1,
campo2,
campo3,
campo4
FROM tabela1
WHERE CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
NOT IN
(SELECT CONCAT(campo1,campo2,campo3,IF(campo4 IS NULL,'',campo4))
FROM tabela2);