Select Multiple Columns From Multiple Tables - mysql

I'm a beginner at MySQL and I'm having a hard time trying to figure out how to solve this problem:
I have two tables with many entries each. Let's say these are the tables:
Table 1 || Table 2
------------- || -------------------
| dt1 | dt2 | || | dt3 | dt4 | dt5 |
------------- || -------------------
| 1 | abc | || | 3 | wsx | 123 |
| 7 | asd | || | 3 | qax | 456 |
| 19 | zxc | || | 4 | rfv | 789 |
------------- || -------------------
What I want to do is to have as a result one table with columns "dt2", "dt4" and "dt5" and with only one entry. For that, the query I'll apply to each table may even have to LIMIT the results. To get the results I want from each table separetelly I would do the following:
SELECT `dt2` FROM `table1` WHERE `dt1`=7;
and
SELECT `dt4`,`dt5` FROM `table2` WHERE `dt3`=3 LIMIT 0,1;
One more thing, I don't want to use a subquery for each column, because in the real thing I'm trying to solve, I'm calling 5 or 6 columns from each table.
Just to make clear, what I want to get is something like this:
-------------------
| dt2 | dt4 | dt5 |
-------------------
| asd | qax | 456 |
-------------------

SELECT a.dt2, b.dt4, b.dt5
FROM table1 a, table2 b
WHERE a.dt2 = 'asd'
LIMIT 0,1;

Ben's answer solved my similar issue.
SELECT t1.dt2, t2.dt4, t2.dt5, t2.dt3 #get dt3 data from table2
FROM table1 t1, table2 t2
WHERE t1.dt2 = 'asd' AND t2.dt4 = 'qax' AND t2.dt5 = 456
| asd | qax | 456 | 3 |
'3' being the data I require by querying the 'qax', 456 data in table2, otherwise you're specifying exactly what data will be returned from the columns.
I only had 2 tables to query in my instance, so the AND expression I can get away with using, it probably isn't best practice and there's most likely a better way for matching data from multiple tables.
EDIT: I've just realised this question is 5 years old.. I hope you achieved what you wanted to by now.

SELECT a.dt2, b.dt4, b.dt5
FROM table1 a, table2 b
WHERE a.dt2 = 'asd'
LIMIT 0,1;
Ben's answer is good, you can use more tables just by separating them by comma (,) , but if there's relationship between those tables then you should use some Sub Query or JOIN

In here there is smth called INNER JOIN , CROSS JOIN , LEFT JOIN and RIGHT JOIN in MYSQL and also SQL Server that allows you yo get data from different tables as much you want via conditions based on your columns;
So let's start :
First Let's create our tables (sample1,sample2) :
--Create Table sample1 :
CREATE TABLE sample1 (id BIGINT NOT NULL AUTO_INCREMEN , name_sample1 VARCHAR(100),age INT);
--Create Table sample2 :
CREATE TABLE sample2 (id BIGINT NOT NULL AUTO_INCREMEN , name_sample2 VARCHAR(100));
-- Now Let's put an trigger in order to avoid getting incorrect values :
DELIMITER $$
CREATE TRIGGER IF NOT EXISTS insert_sample1_trigger BEFORE INSERT ON sample1
FOR EACH ROW
BEGIN
IF NEW.name_sample1 <> "" AND NEW.age <> "0" THEN
INSERT INTO sample2 (name_sample2) VALUES (NEW.name_sample1);
ELSE
INSERT INTO sample1 (name_sample1,age) VALUES ("Unknown" , 10);
INSERT INTO sample2 (name_sample2) VALUES ("Unknown");
END IF;
END$$
DELIMITER ;
After U ran this query , trigger will be added;
--- Now Inserting
INSERT INTO sample1(name_sample1,age) VALUES ("SomeOne Name" , 15);
After running this query the name will be added to sample2 table, because id is auto increment it's not needed to be called in the insert query
id
name_sample1
age
1
SomeOne Name
15
But if I give another value ...
INSERT INTO sample1(name_sample1,age) VALUES ("SomeOne Name" , 0);
id
name_sample1
age
1
Unknown
10
-- Now at last Select query what we were waiting for :
SELECT * FROM sample1 s1 INNER JOIN sample2 s2 USING(id) GROUP BY s1.name_sample1
ORDER BY s1.name_sample1 DESC
This query selects all columns from tables sample1 and sample2 if you want to show some other columns change * via your column name.
That's it

Related

MySQL SELECT Query with WHERE clause Not returning rows from two tables

I have two tables InvoicePDF and UserMaster. They are connected using a common column (CompanyID). When I try to run the below query, I am getting empty result set. Curious to know why?
By the way I wish to return all the rows of the first table matching the CompanyID in the second table where the CustomerID is 3.
SELECT A.CompanyID,
B.COMPANYID,
B.CUSTOMERID,
A.InvPDFFileName,
A.InvMonth,
A.InvYear,
A.InvoiceID
FROM InvoicePDF A, UserMaster B
WHERE B.CompanyID=A.CompanyID and B.CustomerID=3
use left join and apply your condition B.CustomerID=3 in ON Cluase - and always use an explicit join instead of implicit one
SELECT A.CompanyID,B.COMPANYID,
B.CUSTOMERID,A.InvPDFFileName,
A.InvMonth,A.InvYear,A.InvoiceID
FROM InvoicePDF A left join UserMaster B on B.CompanyID=A.CompanyID and B.CustomerID=3
Your query works as expected
DROP TABLE IF EXISTS INVOICEPDF,USERMASTER;
CREATE TABLE INVOICEPDF(COMPANYID INT , InvPDFFileName varchar(3),InvoiceID int);
create table usermaster(COMPANYID int,CUSTOMERID int);
insert into invoicepdf values
(1,'aaa',1),(2,'bbb',2),(1,'aaa',3);
insert into usermaster values
(1,3),(2,4),(3,3);
SELECT A.CompanyID,
B.COMPANYID,
B.CUSTOMERID,
A.InvPDFFileName,
#A.InvMonth,
#A.InvYear,
A.InvoiceID
FROM InvoicePDF A, UserMaster B
WHERE B.CompanyID=A.CompanyID and B.CustomerID=3;
+-----------+-----------+------------+----------------+-----------+
| CompanyID | COMPANYID | CUSTOMERID | InvPDFFileName | InvoiceID |
+-----------+-----------+------------+----------------+-----------+
| 1 | 1 | 3 | aaa | 1 |
| 1 | 1 | 3 | aaa | 3 |
+-----------+-----------+------------+----------------+-----------+
2 rows in set (0.00 sec)
Which means one or more of your where conditions is false.

SELECT where the first two numbers are equal

I have this in my database:
75012
75016
94400
94500
94300
78400
I would like to select only the string where only the first two numbers match and show how many 94 there are so it will output 75012 = 2, 94 = 3, 78 = 1.
Here is what I tried:
select cpostal from fiche_personne WHERE cpostal LIKE LEFT(cpostal, 2);
you need to use a group by clause in your query.
SELECT LEFT(cpostal,2), COUNT(*) AS total
FROM fiche_personne
GROUP BY LEFT(cpostal,2)
please note that the COUNT(*) isn't the best way to complete the query but I don't know your actual table structure, so you should change this to an actual column name
select count(cpostal) from fiche_personne WHERE cpostal LEFT(cpostal, 2) = 94;
Resource: https://www.w3schools.com/sql/func_mysql_count.asp
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(i INT NOT NULL PRIMARY KEY);
INSERT INTO my_table VALUES
(75012),
(75016),
(94400),
(94500),
(94300),
(78400);
SELECT MIN(i) i, COUNT(*) total FROM my_table GROUP BY LEFT(i,2);
+-------+-------+
| i | total |
+-------+-------+
| 75012 | 2 |
| 78400 | 1 |
| 94300 | 3 |
+-------+-------+

SQL - select rows that have the same value in two columns

The solution to the topic is evading me.
I have a table looking like (beyond other fields that have nothing to do with my question):
NAME,CARDNUMBER,MEMBERTYPE
Now, I want a view that shows rows where the cardnumber AND membertype is identical. Both of these fields are integers. Name is VARCHAR. Name is not unique, and duplicate cardnumber, membertype should show for the same name, as well.
I.e. if the following was the table:
JOHN | 324 | 2
PETER | 642 | 1
MARK | 324 | 2
DIANNA | 753 | 2
SPIDERMAN | 642 | 1
JAMIE FOXX | 235 | 6
I would want:
JOHN | 324 | 2
MARK | 324 | 2
PETER | 642 | 1
SPIDERMAN | 642 | 1
this could just be sorted by cardnumber to make it useful to humans.
What's the most efficient way of doing this?
What's the most efficient way of doing this?
I believe a JOIN will be more efficient than EXISTS
SELECT t1.* FROM myTable t1
JOIN (
SELECT cardnumber, membertype
FROM myTable
GROUP BY cardnumber, membertype
HAVING COUNT(*) > 1
) t2 ON t1.cardnumber = t2.cardnumber AND t1.membertype = t2.membertype
Query plan: http://www.sqlfiddle.com/#!2/0abe3/1
You can use exists for this:
select *
from yourtable y
where exists (
select 1
from yourtable y2
where y.name <> y2.name
and y.cardnumber = y2.cardnumber
and y.membertype = y2.membertype)
SQL Fiddle Demo
Since you mentioned names can be duplicated, and that a duplicate name still means is a different person and should show up in the result set, we need to use a GROUP BY HAVING COUNT(*) > 1 in order to truly detect dupes. Then join this back to the main table to get your full result list.
Also since from your comments, it sounds like you are wrapping this into a view, you'll need to separate out the subquery.
CREATE VIEW DUP_CARDS
AS
SELECT CARDNUMBER, MEMBERTYPE
FROM mytable t2
GROUP BY CARDNUMBER, MEMBERTYPE
HAVING COUNT(*) > 1
CREATE VIEW DUP_ROWS
AS
SELECT t1.*
FROM mytable AS t1
INNER JOIN DUP_CARDS AS DUP
ON (T1.CARDNUMBER = DUP.CARDNUMBER AND T1.MEMBERTYPE = DUP.MEMBERTYPE )
SQL Fiddle Example
If you just need to know the valuepairs of the 3 fields that are not unique then you could simply do:
SELECT concat(NAME, "|", CARDNUMBER, "|", MEMBERTYPE) AS myIdentifier,
COUNT(*) AS count
FROM myTable
GROUP BY myIdentifier
HAVING count > 1
This will give you all the different pairs of NAME, CARDNUMBER and MEMBERTYPE that are used more than once with a count (how many times they are duplicated). This doesnt give you back the entries, you would have to do that in a second step.

Deleting database existing record while asigning values from one row to other with unique values

EDIT2: Solved Thanks all for fast reply, appreciate ur help. Specially to Mr Jeremy Smyth for the working solution.
I'm fairly new to sql and cant find a solution to make an update query. I have the following table
Table: order
id | cid | pid
1 | 1 | a1
2 | 1 | a2
3 | 2 | a2
4 | 2 | a3
5 | 2 | a4
I want the cid of 2 to become 1, BUT not updating rows which have same pid i.e(id.2 & id.3).
The result i want is:
id | cid | pid
1 | 1 | a1
2 | 1 | a2
3 | 2 | a2
4 | '1' | a3
5 | '1' | a4
pseudo query example: UPDATE order SET cid=1 WHERE cid=2 AND 1.pid <> 2.pid;
EDIT1: not to confuse pid values with cid and id i changed them with 'a' in start. as suggested i'll not use order as table name.
On update I simply dont want duplicate pid for cid
Sorry for bad English.
I hope I understood you right:
UPDATE `order`
SET cid = 1
WHERE cid = 2
AND cid <> pid
What do you think?
Please notice: ORDER is a reserved word, read more.
I think you need something like this.
UPDATE order SET cid=1 WHERE cid=2 AND cid <> pid;
This can only be done in multiple steps (i.e. not a single UPDATE statement) in MySQL, because of the following points
Point 1: To get a list of rows that do not have the same pid as other rows, you would need to do a query before your update. For example:
SELECT id FROM `order`
WHERE pid NOT IN (
SELECT pid FROM `order`
GROUP BY pid
HAVING COUNT(*) > 1
)
That'll give you the list of IDs that don't share a pid with other rows. However we have to deal with Point 2, from http://dev.mysql.com/doc/refman/5.6/en/subquery-restrictions.html:
In general, you cannot modify a table and select from the same table in a subquery.
That means you can't use such a subquery in your UPDATE statement. You're going to have to use a staging table to store the pids and UPDATE based on that set.
For example, the following code creates a temporary table called badpids that contains all pids that appear multiple times in the orders table. Then, we execute the UPDATE, but only for rows that don't have a pid in the list of badpids:
CREATE TEMPORARY TABLE badpids (pid int);
INSERT INTO badpids
SELECT pid FROM `order`
GROUP BY pid
HAVING COUNT(*) > 1;
UPDATE `order` SET cid = 1
WHERE cid= 2
AND pid NOT IN (SELECT pid FROM badpids);

Duplicating rows in sql query

I have a table containing several fields. The primary key is userId. Currently the user id column contains values '1,2,3,4...etc' like so:
+------+
|userId|
+------+
| 1 |
| 2 |
| 3 |
| 4 |
...etc
I now want to add new rows ending in a,b,c, like so:
+------+
|userId|
+------+
| 1 |
| 1a |
| 1b |
| 1c |
| 2 |
| 2a |
| 2b |
| 2c |
...etc
The new rows should be identical to their parent row, except for the userId. (i.e. 1a,1b & 1c should match 1)
Also I can't guarantee that there won't already be a few 'a', 'b' or 'c's in userid column.
Is there a way to write an sql query to do this quickly and easily?
DON'T DO IT you will run into more problems than the one you are trying to solve!
add a new column to store the letter and make the primary key cover the original UserId and this new column.
If you ever just want the userId, you need to split the letter portion off, which will be expensive for your query and be a real pain.
I agree with KM. I'm not sure why you're creating these duplicate/composite IDs, but it feels like an uncomfortable direction to take.
That said, there is only really one obsticle to overcome; Apparently you can't select from and insert into the same table in MySQL.
So, you need to insert into a Temporary Table first, then insert into the real table...
CREATE Temporary TABLE MyNewUserIDs (
UserID VARCHAR(32)
)
INSERT INTO
myNewUserIDs
SELECT
CONCAT(myTable.UserID, suffix.val)
FROM
myTable
INNER JOIN
(SELECT 'A' as val UNION ALL SELECT 'B' UNION ALL SELECT 'C' UNION ALL SELECT 'D') AS suffix
ON RIGHT(myTable.UserID, 1) <> Suffix.val
WHERE
NOT EXISTS (SELECT * FROM myTable AS lookup WHERE UserID = CONCAT(myTable.UserID, suffix.val))
INSERT INTO
myTable
SELECT
UserID
FROM
MyNewUserIDs
Depending on your environment, you may want to look into locking the tables, so that changes are not made between creating the list of IDs and inserting them into your table.
This is quite simple from a SQL perspective to generate the extra rows: I'll do that here
#Km's answer tells you how to store it as 2 distinct values which I've assumed here. Feel free to concatenate userid and suffix if you prefer.
INSERT myTable (userid, suffix, co11, col2, ...coln)
SELECT M.userid, X.suffix, M.col1, M.col2, ..., M.coln
FROM
myTable M
CROSS JOIN
(SELECT 'a' AS Suffix UNION ALL SELECT 'b' UNION ALL SELECT 'c') X
WHERE
NOT EXISTS (SELECT *
FROM
MyTable M2
WHERE
M2.userid = M.userid ANS M2.Suffix = X.Suffix)