Okay, so I have a table which has 3000 rows. Each row is unique, however some fields are duplicated.
I want to update the rows with fields that are duplicated. I'm having a hard time putting this into words, so I'm sorry if I'm getting it all wrong.
For example, the table looks like this:
+----+--------+--------+-----------+-------+-------+------+--+
| id | name | place | day | time1 | time2 | dupe | |
+----+--------+--------+-----------+-------+-------+------+--+
| 1 | George | Garden | Sunday | 12:00 | 13:00 | 0 | |
| 2 | George | House | Monday | 15:00 | 18:00 | 0 | |
| 3 | David | School | Wednesday | 15:00 | 18:00 | 0 | |
| 4 | Stan | Church | Sunday | 12:00 | 13:00 | 0 | |
+----+--------+--------+-----------+-------+-------+------+--+
I'd like to run a mysql query that checks the table for duplicate names in the name field, and marks the dupe field as 1 if they are a duplicate.
So the dupe fields in row 1 and 2 should be '1' and the rest should be '0'.
Thank you for any help you might be able to provide! I hope I explained it right.
You can use EXISTS in a CASE statement:
select
t.*,
case
when exists (
select 1 from tablename
where id <> t.id and name = t.name
) then 1
else 0
end dupe
from tablename t
You seem to only care about the name field. So:
update t join
(select name
from t
group by name
having count(*) >= 2
) dups
on t.name = dups.name
set dups = 1;
Related
I have the following MySQL table:
+----------+----------+---------+-------------+------------+----------+----------+-----------+
| queue_id | email_id | user_id | customer_id | send_date | campaign | approved | scheduled |
+----------+----------+---------+-------------+------------+----------+----------+-----------+
| 1 | 1 | 1 | 1 | 2018-10-30 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 | 2018-10-30 | 1 | 1 | 1 |
| 3 | 2 | 1 | 1 | 2018-11-02 | 1 | 1 | 1 |
| 4 | 2 | 2 | 1 | 2018-11-02 | 1 | 0 | 1 |
| 5 | 2 | 3 | 1 | 2018-11-02 | 1 | 1 | 1 |
+----------+----------+---------+-------------+------------+----------+----------+-----------+
Where the email_id, user_id, and customer_id are all foreign keys.
What I need to do is return the send_date, subject (which is apart of the email table that the email_id references), and name (which is apart of the business table that the user_id references) but only for columns where the approved column is true. The idea is to ultimately display the data to a user in an HTML table where the table would look like the following (using the sample data provided):
+--------------------+--------------------------+---------------+
| October 30th, 2018 | Subject for email_id "1" | View Approved |
| November 2nd, 2018 | Subject for email_id "2" | View Approved |
+--------------------+--------------------------+---------------+
Whenever the user would click on the "View Approved" cell, then it would display all of the business names that approved that particular email.
I tried using the following query, but it is only returning one value in the name column:
SELECT
DATE_FORMAT(q.`send_date`, "%M %D, %Y") AS `date_visited`,
e.`subject`,
b.`name`
FROM
`email_queue` AS q
INNER JOIN
`email` AS e ON q.`email_id` = e.`email_id`
INNER JOIN
`user` AS u ON q.`user_id` = u.`user_id`
INNER JOIN
`business` AS b ON u.`business_id` = b.`business_id`
WHERE
q.`approved` = true
GROUP BY
e.`email_id`
ORDER BY
q.`send_date` DESC
How can I structure my query to where it would return all of the business names in the name column instead of just one?
You can get all the unqiue business names in a Comma separated string, using Group_Concat() function with Distinct clause.
Try:
GROUP_CONCAT(DISTINCT b.`name` SEPARATOR ',') AS name
instead of:
b.`name`
Note:
You can avoid the usage of Distinct clause, if there would not be any duplicate user_id (for a specific email_id), thus ensuring that b.name is also unique.
You can also use any separator, instead of comma. For eg: to use separator as pipe character |, you would write the query as:
GROUP_CONCAT(DISTINCT b.nameSEPARATOR '|') AS name
i have table like this:
+----+--------------------+-------------------+
| id | name | date_departure |
+----+--------------------+-------------------+
| 1 | karyawan karantina | 2017-02-10 |
| 2 | karyawan berangkat | 2015-11-24 |
| 3 | asdf | 2013-04-18 |
+----+--------------------+-------------------+
i want to show data where date_departure o later than 1 year of departure .
so the expected data like this :
+----+--------------------+-------------------+
| id | nama | tanggal_berangkat |
+----+--------------------+-------------------+
| 2 | karyawan berangkat | 2015-11-24 |
+----+--------------------+-------------------+
please help me... thanks before... sorry for my english. Im indonesian...
Assuming you're after flights within 1 year of current date..
This seems to be a pretty straight forward SQL statement... what's the problem?
Manual with relevant functions
SELECT ID, Name, Date_Departure
FROM tablename
WHERE date_Departure between date_Add(now(),Interval -1 year) and
date_Add(now(),Interval +1 year)
or if you truely mean between now and 1 year from now you don't need the date add on the first segment of the between.
SELECT ID, Name, Date_Departure
FROM tablename
WHERE date_Departure between now and
date_Add(now(),Interval 1 year)
I have a MySQL table called employee that looks like this:
ID | User | Phone_No | Phone_No_Count
1 | Fred | 9999 | 1
2 | John | 8888 | 2
3 | Pablo | 123 | 1
4 | John | | 0
5 | John | 8888 | 2
6 | Pablo | | 0
7 | John | 456 | 1
Phone_No_Count is a count of the Phone_No column, if there is no Phone_No then Phone_No_Count is set to zero.
I want to backfill the missing Phone_No entries using Phone_No entries which have the highest Phone_No_Count.
e.g. User John has 2 Phone_No's (8888 and 456) so I just want to use 8888 as it has the highest Phone_No_Count (2)
The backfilled data in employee would then look like this:
ID | User | Phone_No | Phone_No_Count
1 | Fred | 9999 | 1
2 | John | 8888 | 2
3 | Pablo | 123 | 1
4 | John | 8888 | 0
5 | John | 8888 | 2
6 | Pablo | 123 | 0
7 | John | 456 | 1
I can then update the Phone_No_Count separately, which I know how to do anyway.
All the examples I've seen online are for backfilling multiple tables or if it's just one table they don't have the required logic for this.
Can somebody please help as this has been frying my brain all day!!
One way to go about this kind of update you can use user defined variables in your query and store the phone for the user which has the maximum of phone count (i.e a correlated subquery) then join this data with your table and do update
update Table1 t1a
inner join(
select t1.id,
t1.`User`,
#p:= case
when t1.Phone_No is null then #c
else t1.Phone_No END Phone_No,
#c:=(select Phone_No from Table1 where t1.`User`=`User` order by `Phone_No_Count` DESC limit 1 ) max_phone
from Table1 t1,(select #p:=0,#c:=0) t
order by t1.`User`,t1.`Phone_No_Count` DESC
) t2 on(t1a.id=t2.id)
set t1a.Phone_No = t2.Phone_No
Fiddle Demo
The trick is to get the phone number for the highest count. Unfortunately, MySQL doesn't let you have subqueries on the same query being updated, but you can do this with a trick. This allows you to use update/join syntax:
update employee e join
(select e.user,
substring_index(group_concat(phone_no order by phone_no_count desc
), ',', 1) as new_phone_no
from employee e
group by e.user
) toupdate
on e.user = toupdate.user
set e.phone_no = toupdate.new_phone_no
where e.phone_no is null;
I have 2 tables named tbl_sales and tbl_rsales.
Lets assume that i have these ff value for "tbl_sales"
id | pcode | total |
2 | 12345 | 10 |
3 | 12345 | 10 |
Lets assume also that i have these ff value from "tbl_rsales"
id | sales_id | total | pcode |
1 | 1 | 20 | 55555 |
2 | 2 | 10 | 12345 |
3 | 3 | 10 | 12345 |
I can easily update data from "tbl_sales" but my problem is that when i update all value by "pcode" from tbl_sales "tbl_rsales" must be update also. but only those id's from "tbl_sales" that are in "sales_id" from tbl_rsales will update. so in other word. sales_id 1 from "tbl_rsales" will not update only sales_id 2 and 3 will be update because tbl_sales id and tbl_rsales "sales_id" is the same. it's lil complicated for me.any idea is accepted.
UPDATE sales, rsales
SET sales.pcode=rsales.pcode
WHERE sales.id=rsales.id
AND id IN(2,3)
Is this what your looking for?
UPDATE TBL_SALES , TBL_RSALES
SET //WAHTEVER YOU WANT FROM THE TABLE
WHERE TBL_SALES,PCODE = TBL_RSALES.PCODE
I have a table with columns start_date and end_date. What we need to do is Select everything and group them by date conflicts for each Object_ID.
A date conflict is when a row's start date and/or end date pass through another rows'. For instance, here are some examples of conflicts:
Row 1 has dates 1st through the 5th, Row 2 has dates 2nd through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 3rd.
Row 1 has dates 2nd through the 5th, Row 2 has dates 3rd through the 6th.
Row 1 has dates 2nd through the 5th, Row 2 has dates 1st through the 7th.
So for example, if we have some sample data (assume the numbers are just days of the month for simplicity):
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
What i would expect to see is this:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 2
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
And for a Second Test Case, Here is some sample data:
id | object_id | start_date | end_date
1 | 1 | 1 | 5
2 | 1 | 2 | 4
3 | 1 | 6 | 8
4 | 2 | 2 | 3
5 | 2 | 4 | 5
6 | 1 | 2 | 3
7 | 1 | 10 | 12
8 | 1 | 11 | 13
And for the second Test Case, what I would expect to see as output:
object_id | start_date | end_date | numconflicts
1 | <na> | <na> | 3
1 | 6 | 8 | 0 or null
2 | 2 | 3 | 0 or null
2 | 4 | 5 | 0 or null
1 | <na> | <na> | 2
Yes, I will need some way of differentiating the first and the second grouping (the first and last rows) but I haven't quite figured that out. The goal is to view this list, and then when you click on a group of conflicts you can view all of the conflicts in that group.
My first thought was to attempt some GROUP BY CASE ... clause but I just wrapped by head around itself.
The language I am using to call mysql is php. So if someone knows of a php-loop solution rather than a large mysql query i am all ears.
Thanks in advance.
Edit: Added in primary Keys to provide a little less confusion.
Edit: Added in a Test case 2 to provide some more reasoning.
This query finds the number of duplicates:
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3;
You can use this query as the basis of a query that gives you exactly what you asked for (see below for output).
select
object_id,
case dups when 0 then start_date else '<na>' end as start_date,
case dups when 0 then end_date else '<na>' end as end_date,
sum(dups) as dups
from (
select od1.object_id, od1.start_date, od1.end_date, sum(od2.id is not null) as dups
from object_date od1
left join object_date od2
on od2.object_id = od1.object_id
and od2.end_date >= od1.start_date
and od2.start_date <= od1.end_date
and od2.id != od1.id
group by 1,2,3) x
group by 1,2,3;
Note that I have used an id column to distinguish the rows. However, you could replace the test of id's not matching with comparisons on every column, ie replace od2.id != od1.id with tests that every other column is not equal, but that would require a unique index on all the other columns to make sense, and having an id column is a good idea anyway.
Here's a test using your data:
create table object_date (
id int primary key auto_increment,
object_id int,
start_date int,
end_date int
);
insert into object_date (object_id, start_date, end_date)
values (1,1,5),(1,2,4),(1,6,8),(2,2,3);
Output of first query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 1 | 5 | 1 |
| 1 | 2 | 4 | 1 |
| 1 | 6 | 8 | 0 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Output of second query when run against this sample data:
+-----------+------------+----------+------+
| object_id | start_date | end_date | dups |
+-----------+------------+----------+------+
| 1 | 6 | 8 | 0 |
| 1 | <na> | <na> | 2 |
| 2 | 2 | 3 | 0 |
+-----------+------------+----------+------+
Oracle : This could be done with a subquery in a group by CASE statement.
https://forums.oracle.com/forums/thread.jspa?threadID=2131172
Mysql : You could have a view which had all the conflicts .
select distinct a1.appt, a2.appt from appointment a1, appointment a2 where a1.start < a2.end and a1.end > a2.start.
and then simply do a count(*) on that table.
Something like the following should work:
select T1.object_id, T1.start_date, T1.end_date, count(T1.object_id) as numconflicts
from T1
inner join T2 on T1.start_date between T2.start_date and T2.end_date
inner join T3 on T1.end_date between T2.start_date and T2.end_date
group by T1.object_id
I might be off a little bit, but it should help you get started.
Edit: Indented it properly