I am trying to accomplish the following sql statement but I am getting one duplicate id in my response.
SELECT ci.customer_id,
ci.first_name,
ci.user_gender,
ci.customer_status,
fr.relation
FROM customerinfo ci
INNER JOIN familyrelation fr
ON ( fr.personid_two = ci.customer_id )
WHERE ci.customer_id IN (SELECT personid_two
FROM familyrelation
WHERE personid_one = 17)
AND ci.csp_user_id = 5;
When i run this query, I am fetching the proper result, but one customer_id is getting repeated. Any help/advice greatly appreciated.
If your data looks like this
drop table if exists ci,fr;
create table ci(customer_id int, name varchar(3),csp_user_id int);
create table fr(personid_one int,personid_two int,relation varchar(10));
insert into ci values (1,'aaa',5),(2,'bbb',5);
insert into fr values (17,1,'mother'),(17,1,'father'),(17,2,'niece');
Then your query selects the rows I would expect
SELECT ci.customer_id,
ci.name,
fr.relation
FROM ci
INNER JOIN fr
ON ( fr.personid_two = ci.customer_id )
WHERE ci.customer_id IN (SELECT personid_two
FROM fr
WHERE personid_one = 17)
AND ci.csp_user_id = 5;
+-------------+------+----------+
| customer_id | name | relation |
+-------------+------+----------+
| 1 | aaa | mother |
| 1 | aaa | father |
| 2 | bbb | niece |
+-------------+------+----------+
3 rows in set (0.00 sec)
Related
I have a table named 'products' and another table named 'rates' that has one to many relation with 'products' table. For each product i have two rows in 'rates' table that i want update one boolean column named 'index' to 1 for each 'product' in 'rates' table.
i used this query :
UPDATE ( SELECT
products.id AS productId,
products.name ,
X.`index` AS `index`,
x.id AS rateId,
x.price, x.discount
FROM products JOIN ( SELECT rates.*
FROM rates
) AS x
WHERE products.id = x.product_id
GROUP BY products.id
) AS y
SET y.index = 1
but id got this error massage:
SQL Error (1288) the target table y of the update is not updatable
i'm new in mysql and i don't know where is my mistake.Thank you for helping
Products Table
| id | name
| 1 | chair
| 2 | bench
Rates Table
| id | product_id | index | value
| 1 | 1 | 0 | xx ==> index = 1
| 2 | 1 | 0 | yy
| 3 | 2 | 0 | zz ==> index = 1
| 4 | 2 | 0 | tt
i want update index column for each product in rates to 1
It looks like you want to update the "first" row in rates for each product_id. If so, you can self-join the table with an aggregate query that computes the minimum id per product_id:
update rates r
inner join (select product_id, min(id) id from rates group by product_id) r1
on r1.id = r.id
set r.index = 1
I have a table like the below:
Site | Name | ID
A | Mike | 1
A | Mary | 2
A | Mary | 3
B | Mary | 1
B | Rich | 2
I'd like to find all the duplicate Name's within a Site. So I'm trying to return:
Site | Name | ID
A | Mary | 2
A | Mary | 3
I've tried this:
SELECT DISTINCT Site, Name, ID
from table
group by ID having count(*) > 1
The results come back erroneously because it's counting Sites A & B together. I would like to only find the duplicates for within each Site--not duplicates across Sites.
You can use exists or in:
select t.*
from t
where exists (select 1
from t t2
where t2.site = t.site and t2.name = t.name and t2.id <> t.id
);
You can try to use NOT exists with subquery having.
the duplicate Name's within a Site
CREATE TABLE T(
Site varchar(5),
Name varchar(5),
ID int
);
insert into t values ('A','Mike', 1);
insert into t values ('A','Mary', 2);
insert into t values ('A','Mary', 3);
insert into t values ('B','Mary', 1);
insert into t values ('B','Rich', 2);
Query 1:
SELECT * FROM T t1 WHERE
NOT exists
(
SELECT 1
FROM T tt
where t1.name = tt.name
group by Name
HAVING MIN(tt.ID) = t1.ID
)
Results:
| Site | Name | ID |
|------|------|----|
| A | Mary | 2 |
| A | Mary | 3 |
find the duplicates for within each Site
CREATE TABLE T(
Site varchar(5),
Name varchar(5),
ID int
);
insert into t values ('A','Mike', 1);
insert into t values ('A','Mary', 2);
insert into t values ('A','Mary', 3);
insert into t values ('B','Mary', 1);
insert into t values ('B','Rich', 2);
Query 1:
SELECT t1.*
FROM T t1
WHERE not exists
(
SELECT 1
FROM T tt
where t1.name = tt.name and t1.Site = tt.Site
group by Name,Site
HAVING MIN(tt.ID) = t1.ID
)
Results:
| Site | Name | ID |
|------|------|----|
| A | Mary | 3 |
I am using MySql.
I have table job that has a primary key job_pk_id and the table stores details of every job. Also I have a table job_running_status where job table's job_pk_id is a foreign key and this table basically contains records of when a job ran for each job_pk_id.There will be multiple entries for the same job_pk_id as the same job runs multiple times. job_running_status table also has a field job_start_time that gives the start time for each instance of the running of the job.
Now my requirement is to get the latest job_running_status for every job . The latest job_running_status would be chosen based on the latest job_start_time(for that particular job only) value in job_running_status.
I know this can be achieved using INNER JOIN and ORDER BY job_start_time desc between job table and job_running_status table but my challenge is this ORDER BY becomes applicable across all the jobs in the JOIN but I need to be applicable only across records that are corresponding to a particular job.
EDIT
I understand it might be confusing to understand me by just reading so I am providing some examples:
job table:
job_running_status table:
My final requirement after joining both the tables
Note: while joining I a should be getting only 1 record corresponding to every JOB table record. This record is chosen based on the latest job_start_time for that JOB.
An example of a correlated sub query in a where clause
drop table if exists t,t1;
create table t(id int);
create table t1(jid int,dt date);
insert into t values
(1),(2),(3);
insert into t1 values
(1,'2018-01-01'),
(1,'2018-02-01'),
(2,'2018-01-01'),
(3,'2018-01-01'),
(3,'2018-02-01'),
(3,'2018-03-01');
select t.id,t1.dt
from t
join t1 on t1.jid = t.id
where t1.dt =(select max(dt) from t1 where t1.jid = t.id);
+------+------------+
| id | dt |
+------+------------+
| 1 | 2018-02-01 |
| 2 | 2018-01-01 |
| 3 | 2018-03-01 |
+------+------------+
3 rows in set (0.00 sec)
If you need the latest n records and you are not on version 8.0 or higher you can use row number simulation
select t.id,s.dt
from t
join
(select t1.jid,t1.dt ,
if(t1.jid<>#p,#rn:=1,#rn:=#rn+1) rn,
#p:=t1.jid p
from t1
cross join (select #rn:=0,#p:=0) r
order by t1.jid ,t1.dt desc
) s on s.jid = t.id
where s.rn <= 2;
+------+------------+
| id | dt |
+------+------------+
| 1 | 2018-01-01 |
| 1 | 2018-02-01 |
| 2 | 2018-01-01 |
| 3 | 2018-02-01 |
| 3 | 2018-03-01 |
+------+------------+
You can try this query. CROSS JOIN with subquery, which get MAX(job_running_status)
Then join job and job_running_status tables.
TestDLL
CREATE TABLE JOB(
job_pk_id int
);
INSERT INTO JOB VALUES (1),(2),(3);
CREATE TABLE job_running_status(
fk_job_id INT,
job_running_status DATE
);
INSERT INTO job_running_status VALUES (1,'2018-01-01');
INSERT INTO job_running_status VALUES (1,'2018-02-01');
INSERT INTO job_running_status VALUES (2,'2018-01-03');
INSERT INTO job_running_status VALUES (2,'2018-01-02');
Query
SELECT DISTINCT
j.job_pk_id,
jrs.fk_job_id,
t.job_running_status
FROM
(SELECT MAX(job_running_status) job_running_status FROM job_running_status) t
CROSS JOIN job j
inner join job_running_status jrs on j.job_pk_id = jrs.fk_job_id
[Results]:
| job_pk_id | fk_job_id | job_running_status |
|-----------|-----------|--------------------|
| 1 | 1 | 2018-02-01 |
| 2 | 2 | 2018-02-01 |
sqlfiddle
Hi these two SQL Queries return the same result
SELECT DISTINCT ItemID
FROM Sale INNER JOIN Department
ON Department.DepartmentID = Sale.DepartmentID
WHERE DepartmentFloor = 2
ORDER BY ItemID
SELECT DISTINCT ItemID
FROM Sale
WHERE EXISTS
(SELECT *
FROM Department
WHERE Sale.DepartmentID = Department.DepartmentID
AND DepartmentFloor = 2)
ORDER BY ItemID;
The Subquery Inside the Exists returns True So why doesnt the secod query return the equivalent of
SELECT DISTINCT ItemID
FROM Sale
Which guves a different result from the two above.
You are getting confused by EXISTS().. It occurs on a line by line basis, based on table correlation, not just a single true/false. This line of your subquery is your correlation clause:
Sale.DepartmentID = Department.DepartmentID
It is saying "Only show the Sale.ItemIDs where that ItemID's Sale.DepartmentID is in Department."
It achieves the same function as a join predicate, like in your first query:
FROM Sale S
JOIN Department D on S.DepartmentID = D.DepartmentID --here
Conversely, this query:
SELECT DISTINCT ItemID
FROM Sale
Has no limiting factor.
As an aside, you also further limit the results of each query with:
WHERE DepartmentFloor = 2
But I don't think that is the part that is throwing you off, I think it is the concept that a correlated subquery occurs for each record. If you were to remove your correlating clause, then the subquery would actually return true always, and you would get all results back.
The subquery isn't always returning true. It will evaluate for each row, joining on DepartmentID where the DepartmentFloor is 2.
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Sale ( ItemID int, DepartmentID int ) ;
INSERT INTO Sale ( ItemID, DepartmentID )
VALUES (1,1), (2,2), (3,3), (4,1), (5,4), (6,2), (7,3), (8,4) ;
CREATE TABLE Department ( DepartmentID int, DepartmentFloor int ) ;
INSERT INTO Department ( DepartmentID, DepartmentFloor )
VALUES (1,1), (2,1), (3,2), (4,2) ;
Query 1:
SELECT *
FROM Department
WHERE DepartmentFloor = 2
Results: This lists only the Departments on DepartmentFloor 2.
| DepartmentID | DepartmentFloor |
|--------------|-----------------|
| 3 | 2 |
| 4 | 2 |
Query 2:
SELECT *
FROM Sale
Results: This lists ALL of your Sales.
| ItemID | DepartmentID |
|--------|--------------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 1 |
| 5 | 4 |
| 6 | 2 |
| 7 | 3 |
| 8 | 4 |
Query 3:
SELECT *
FROM Sale
WHERE DepartmentID IN (3,4)
Results: And this one shows what is the equivalent of you EXISTS statement. It only shows 4 rows that will match up in my data. So you'd only get back ItemIDs 3,5,7 and 8.
| ItemID | DepartmentID |
|--------|--------------|
| 3 | 3 |
| 5 | 4 |
| 7 | 3 |
| 8 | 4 |
because the uppper part of the query is equivalent to
SELECT DISTINCT ItemID FROM Sale where EXISTS (true)
the upper is the only query that really check the condition ..
I am trying to get some rows from the same table. It's a user table: user has user_id and user_parent_id.
I need to get the user_id row and user_parent_id row. I have coded something like this:
SELECT user.user_fname, user.user_lname
FROM users as user
INNER JOIN users AS parent
ON parent.user_parent_id = user.user_id
WHERE user.user_id = $_GET[id]
But it doesn't show the results. I want to display user record and its parent record.
I think the problem is in your JOIN condition.
SELECT user.user_fname,
user.user_lname,
parent.user_fname,
parent.user_lname
FROM users AS user
JOIN users AS parent
ON parent.user_id = user.user_parent_id
WHERE user.user_id = $_GET[id]
Edit:
You should probably use LEFT JOIN if there are users with no parents.
You can also use UNION like
SELECT user_fname ,
user_lname
FROM users
WHERE user_id = $_GET[id]
UNION
SELECT user_fname ,
user_lname
FROM users
WHERE user_parent_id = $_GET[id]
Perhaps this should be the select (if I understand the question correctly)
select user.user_fname, user.user_lname, parent.user_fname, parent.user_lname
... As before
Your query should work fine, but you have to use the alias parent to show the values of the parent table like this:
select
CONCAT(user.user_fname, ' ', user.user_lname) AS 'User Name',
CONCAT(parent.user_fname, ' ', parent.user_lname) AS 'Parent Name'
from users as user
inner join users as parent on parent.user_parent_id = user.user_id
where user.user_id = $_GET[id];
I don't know how the table is created but try this...
SELECT users1.user_id, users2.user_parent_id
FROM users AS users1
INNER JOIN users AS users2
ON users1.id = users2.id
WHERE users1.user_id = users2.user_parent_id
Lets try to answer this question, with a good and simple scenario, with 3 MySQL tables i.e. datetable, colortable and jointable.
first see values of table datetable with primary key assigned to column dateid:
mysql> select * from datetable;
+--------+------------+
| dateid | datevalue |
+--------+------------+
| 101 | 2015-01-01 |
| 102 | 2015-05-01 |
| 103 | 2016-01-01 |
+--------+------------+
3 rows in set (0.00 sec)
now move to our second table values colortable with primary key assigned to column colorid:
mysql> select * from colortable;
+---------+------------+
| colorid | colorvalue |
+---------+------------+
| 11 | blue |
| 12 | yellow |
+---------+------------+
2 rows in set (0.00 sec)
and our final third table jointable have no primary keys and values are:
mysql> select * from jointable;
+--------+---------+
| dateid | colorid |
+--------+---------+
| 101 | 11 |
| 102 | 12 |
| 101 | 12 |
+--------+---------+
3 rows in set (0.00 sec)
Now our condition is to find the dateid's, which have both color values blue and yellow.
So, our query is:
mysql> SELECT t1.dateid FROM jointable AS t1 INNER JOIN jointable t2
-> ON t1.dateid = t2.dateid
-> WHERE
-> (t1.colorid IN (SELECT colorid FROM colortable WHERE colorvalue = 'blue'))
-> AND
-> (t2.colorid IN (SELECT colorid FROM colortable WHERE colorvalue = 'yellow'));
+--------+
| dateid |
+--------+
| 101 |
+--------+
1 row in set (0.00 sec)
Hope, this would help many one.