SQL Query to Find Duplicate form two different tables - mysql

I have two tables ganadordia and ganadornoche with numbers in column winNumber for both tables. I would like to create a new table based on the duplicated numbers found in each table
However, I'm encountering an issue: winNumber is creating an additional duplicate. For example, if I have two numbers 101 instead of getting only 2 I get 3
SELECT Distinct ganadoresdia.winNumber as 'Winner Day',ganadoresdia.Month as 'Month Day', ganadoresnoche.winNumber as ' Winner Night',
ganadoresnoche.month as 'Month Night'
FROM ganadoresdia, ganadoresnoche
where ganadoresnoche.winNumber = ganadoresdia.winNumber
ORDER BY ganadoresdia.winNumber asc
Does anyone know how to fix this? it show 13 instead of 8
Table Example
This is the result for ganadornocheit should only display 5
exemple
This is the result for ganadordia it should only display 3
example

From your sample I assume what you actually want to do is union the data rather than join (5+3=8). To do a join you need a primary:foreign key relationship, which you don't seem have.
SELECT 'day' as day_night_indicator,
winNumber,
month
FROM ganadoresdia
UNION
SELECT 'night' as day_night_indicator,
winNumber,
month
FROM ganadoresnoche

Related

Looking for a low footprint solution to GROUP rows using HAVING to filter

Here is a table
id date name
1 180101 josh
2 180101 peter
3 180101 julia
4 180102 robert
5 180103 patrick
6 180104 josh
7 180104 adam
I need to get all the names whom having the same days as 'josh'. how can i achieve it without groupping the whole table together. i need to keep it efficient (this is not my real table, i just simplified my problem here, and i have hundred thousands of records, and 99% of the rows have different dates, so groupable rows by date is kind of rare).
So basicaly what i want is: if 'josh' is the target, i need to get 'josh,peter,julia,adam' (actually the first 10 distinct names sharing the same date with josh).
SELECT
COUNT(date) as datecount,
GROUP_CONCAT(DISTINCT name) as names,
FROM
table
GROUP BY
date
HAVING
datecount>1
// && name IN ('josh') would work nice for me, but im getting error because 'name' is not in GROUPED BY
LIMIT 10
Any idea ? As i mentioned it needs to be fast, and most of the rows have unique dates
Join the table with itself on date:
select distinct t1.name
from tbl t1
join tbl t2 using (date)
where t2.name = 'josh'
Demo
For the best performance you would have indexes on (name) and (date, name).

SQL Capture duplicate records across two DIFFERENT columns

I am writing an Exception Catching Page using MySQL for catching duplicate billing entries the following scenario.
Items details are entered in a table which has the following two columns (among others).
ItemCode VARCHAR(50), BillEntryDate DATE
It often happens that same item's bill is entered multiple times, but over a period of few days. Like,
"Football","2019-01-02"
"Basketball","2019-01-02"
...
...
"Football","2019-01-05"
"Rugby","2019-01-05"
...
"Handball","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"
In the above example, the item Football is billed twice - first on 2Jan and again on 5Jan. Similarly, item Rugby is billed thrice on 5,7,10Jan.
I am looking to write simple SQL which can pickup each item [say, using distinct(ItemCode) clause], and then display all the records which are duplicates over a period of 30 days.
In the above case, the expected output should be the following 5 records:
"Football","2019-01-02"
"Football","2019-01-05"
"Rugby","2019-01-05"
"Rugby","2019-01-07"
"Rugby","2019-01-10"
I am trying to run the following SQL:
select * from tablen a, tablen b, where a.ItemCode=b.ItemCode and a.BillEntryDate = b.BillEntryDate+30;
However, this seems to be highly inefficient as it is running for long without displaying any records.
Is there any possibility for getting a less complex and faster method?
I did explore existing topics (like How do I find duplicates across multiple columns?), but it is catching duplicates where BOTH columns have same value. My requirement is one column same value, and second column varying over a month-long date range.
You can use:
select t.*
from tablen t
where exists (select 1
from tablen t2
where t2.ItemCode = t.ItemCode and
t2.BillEntryDate <> t.BillEntryDate and
t2.BillEntryDate >= t1.BillEntryDate - interval 30 day and t2.BillEntryDate <= t1.BillEntryDate + interval 30 day
);
This will pick up both duplicates in the pair.
For performance, you want an index on (ItemCode, BillEntryDate).
With EXISTS:
select ItemCode, BillEntryDate
from tablename t
where exists (
select 1 from tablename
where
ItemCode = t.ItemCode
and
abs(datediff(BillEntryDate, t.BillEntryDate)) between 1 and 30
)

Gathering data from three separate tables, sql

I have three separate tables that represent student attendance for three weeks, respectively. I want to be able to generate four columns that break down the attendance by week for each of the students. If a student was present multiple times a week, the number of times present should be added. Also, if a student was present in one week and not the next, it would get 1 for the month present (assuming it was only present once) and and 0 for the one absent. I have tried to multiple variations of count() and joins but to no avail. Any help would be greatly appreciated. The following is a truncated fiddle:
http://www.sqlfiddle.com/#!9/b847a
Here is a sample of what I am trying to achive:
Name | CurrWeek | LastWeek | TwoWkAgo
Paula | 0 | 2 | 3
Rather than three tables you should have only one with a column for the week. So naturally one solution for your request is to build it on-the-fly with UNION ALL:
select
name,
sum(week = 'currentWeek') as currentWeek,
sum(week = 'lastWeek') as lastWeek,
sum(week = 'thirdWeek') as thirdWeek
from
(
select 'currentWeek' as week, name from currentWeek
union all
select 'lastWeek' as week, name from lastWeek
union all
select 'thirdWeek' as week, name from thirdWeek
) all_weeks
group by name
order by name;
(If you want to join the three tables instead, you'd need full outer joins, which MySQL does not support, if I remember correctly. Anyway, my advice is to change the data model.)
You can try this query:
select currweek.name, currweek.att, lastweek.att, twoWkAgo.att from
(select name, count(attendance) as att from currentWeekTable group by name) currweek,
(select name, count(attendance) as att from lastWeekTable group by name) lastweek,
(select name, count(attendance) as att from twoWeekTable group by name) twoWkAgo
where twoWkAgo.name=currWeek.name and twoWkAgo.name=lastweek.name;
Assuming your 3 attendance tables contain name as common field.

How to explode in MySQL and use it in the WHERE clause of the query - MySQL

I have a database table as below.
Promotion_Table
id(INT), promotion_name(VARCHAR),......, bungalow_ids(VARCHAR)
We can add a promotion for a bungalow(23). So a row is added with the bungalow id as below.
1, My Promotion, ........, 23
But if I single a promotion is added for a multiple bungalows(23,42) all ids are saved in the bungalow_ids column as below.
2, My Promotion 2, ........, 23 | 42
If a user search for promotion which are for specific bungalow(23) All promotions for the bungalow should be shown in the result.
I have a query as below.
SELECT * FROM Promotion_Table WHERE bungalow_ids = '23'
It only gets 1 rows. But actually 2nd row should be shown too since there is a offer. I can nt use LIKE since it gets wrong records.
Given that I have already referred below links but I have no idea how to use them in the query.
Can you split/explode a field in a MySQL query?
Equivalent of explode() to work with strings in MySQL
How can I fix this? How can I explode the column data and use it in the query ?
Use , to separate the string and try this query
select * from promotion_table where FIND_IN_SET("23",bungalow_ids)
http://sqlfiddle.com/#!2/7bbcb/1
The previous Answer is the right decision but if you insist in your model.
Probably what you want to do is:
SELECT *
FROM Promotion_Table
WHERE bungalow_ids = '23'
OR bungalow_ids LIKE '23,*'
OR bungalow_ids LIKE '*,23'
OR bungalow_ids LIKE '*,23,*'
this assuming the numbers are separated by ",".
But this is the wrong way, make the changes to the DB as stated in the previous answer.
you need to reformat your DB schema.
you need to construct 2 tables one for promotions and one for bangalows.
like below:
promotions: Promotion_id(int), Promotion_desc
bangalows: Bangalow_id(int), Promotion_id(int)
tables example:
promotion :
1 myPromotion
2 secondPromotion
bangalows:
1 1
2 2
3 1
4 1
once you create above two tables, the following query will work and returns 1,3,4:
SELECT Bangalow_id FROM Promotion_Table WHERE bungalow_id = '1'

Can SQL query do this?

I have a table "audit" with a "description" column, a "record_id" column and a "record_date" column. I want to select only those records where the description matches one of two possible strings (say, LIKE "NEW%" OR LIKE "ARCH%") where the record_id in each of those two matches each other. I then need to calculate the difference in days between the record_date of each other.
For instance, my table may contain:
id description record_id record_date
1 New Sub 1000 04/14/13
2 Mod 1000 04/14/13
3 Archived 1000 04/15/13
4 New Sub 1001 04/13/13
I would want to select only rows 1 and 3 and then calculate the number of days between 4/15 and 4/14 to determine how long it took to go from New to Archived for that record (1000). Both a New and an Archived entry must be present for any record for it to be counted (I don't care about ones that haven't been archived). Does this make sense and is it possible to calculate this in a SQL query? I don't know much beyond basic SQL.
I am using MySQL Workbench to do this.
The following is untested, but it should work asuming that any given record_id can only show up once with "New Sub" and "Archived"
select n.id as new_id
,a.id as archive_id
,record_id
,n.record_date as new_date
,a.record_date as archive_date
,DateDiff(a.record_date, n.record_date) as days_between
from audit n
join audit a using(record_id)
where n.description = 'New Sub'
and a.description = 'Archieved';
I changed from OR to AND, because I thought you wanted only the nr of days between records that was actually archived.
My test was in SQL Server so the syntax might need to be tweaked slightly for your (especially the DATEDIFF function) but you can select from the same table twice, one side grabbing the 'new' and one grabbing the 'archived' then linking them by record_id...
SELECT
newsub.id,
newsub.description,
newsub.record_date,
arc.id,
arc.description,
arc.record_date,
DATEDIFF(day, newsub.record_date, arc.record_date) AS DaysBetween
FROM
foo1 arc
, foo1 newsub
WHERE
(newsub.description LIKE 'NEW%')
AND
(arc.description LIKE 'ARC%')
AND
(newsub.record_id = arc.record_id)