SQL Compare rows - mysql

Okay here is the situation:
I the following data in a table.
PAIR_NO NO NO2
3 5678EFGH 1234ABCD
4 1111BBBB 0000AAAA
1 1234ABCD 5678EFGH
2 0000AAAA 1111BBBB
The constraints are if no = no2 in another row skip that row.
So in this sample data the only rows that would be selected should be pair no 3 and 4.
I have tried to merge and inner join with self but I just keep getting all 4 rows back.
I have tried to insert into a table where not exists but again I get 4 rows inserted.
SELECT a.* from PAIRS a
inner join PAIRS b on a.no=b.no2 and a.no2=b.no;
I was thinking maybe selecting distinct number from column 1 and then check those in column 2 but I think that would yield the same four rows.
I may be over thinking this problem and maybe some here can look at this and see where the solution is hiding.
I am currently testing this on MySQL but it should run on SQLServer 2008. I have searched but all the questions didn't seem to match my data set issue.

Taking you at your word, meaning selecting all records where the value of no column does not appear anywhere in no2 column in the same table, try this:
SELECT A.PAIR_NO, A.NO, A.NO2
FROM PAIRS A
LEFT JOIN PAIRS B ON(A.NO = B.NO2)
WHERE B.PAIR_NO IS NULL -- assuming this column is not nullable
Another option is to use NOT EXISTS:
SELECT PAIR_NO, NO, NO2
FROM PAIRS A
WHERE NOT EXISTS(
SELECT 1
FROM PAIRS B
WHERE B.NO2 = A.NO
)
I personally prefer the LEFT JOIN option since it's shorter and more readable.
Both of these statement should work on both MySql and Sql Server.

Okay fellas I want to thank you all for helping, but I think I solved my issue. Took me a second but I believe this is what I am after (SQL Server 2008):
if OBJECT_ID('tempdb..#pairs') is not null drop table #pairs
if OBJECT_ID('tempdb..#pairs_final') is not null drop table #pairs_final
create table #pairs(pair_no int, a_no varchar(17),a_no2 varchar(17))
create table #pairs_final(pair_no int Identity(1,1), a_no varchar(17),a_no2 varchar(17))
insert into #PAIRS values(1,'1234ABCD','5678EFGH');
insert into #PAIRS values(1,'1234ABCD','XXXX9999');
insert into #PAIRS values(2,'0000AAAA','1111BBBB');
insert into #PAIRS values(3,'5678EFGH','1234ABCD');
insert into #PAIRS values(4,'1111BBBB','0000AAAA');
insert into #PAIRS values(1,'XXXX9999','1234ABCD');
insert into #pairs_final
select a.a_no,a.a_no2 from #pairs a
join (
select distinct a_no_p from(
select pair_no,a_no_p,
ROW_NUMBER() over (partition by pair_no order by a_no_p) as RN
from #pairs
unpivot(
a_no_p for clms in (a_no2,a_no)
) as umpvt
) as mypairs
where RN = 1
) as my_pairs on my_pairs.a_no_p=a.a_no
select * from #pairs_final
This will give me the following results:
pair_no a_no a_no2
1 1234ABCD 5678EFGH
2 1234ABCD XXXX9999
3 0000AAAA 1111BBBB
Hope this might help someone else.
Enjoy.

DECLARE #TBL AS TABLE
(
[NO] INT,
[CODE] VARCHAR(50),
[AREA] VARCHAR(50)
)
/* EXAMPLE 1 */
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (1,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (2,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (3,'001','B00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (4,'001','C00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (5,'001','C00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (6,'001','A00')
INSERT INTO #TBL([NO],[CODE],[AREA]) VALUES (7,'001','A00')
/* EXAMPLE 2 */
/* ***** USE THIS CODE TO ENTER DATA FROM DIRECT TABLE *****
SELECT
ROW_NUMBER() OVER(ORDER BY [FIELD_DATE]) AS [NO]
,[FIELD_CODE] AS [CODE]
,[FIELD_AREA] AS [AREA]
FROM TABLE_A
WHERE CAST([FIELD_DATE] AS DATE) >= CAST('20200307' AS DATE)
ORDER BY [FIELD_DATE],[FIELD_CODE]
*/
SELECT
A.NO AS ANO
,A.CODE AS ACODE
,A.AREA AS AAREA
,B.NO AS BNO
,B.CODE AS BCODE
,B.AREA AS BAREA
,CASE WHEN A.AREA=B.AREA THEN 'EQUAL' ELSE 'NOT EQUAL' END AS [COMPARE AREA]
FROM #TBL A
LEFT JOIN #TBL B
ON A.NO=B.NO+1

Related

Different actions based on SELECT result

There are 3 tables (First, Second and Third). I need to check condition in table First and then make an action in Second or Third depend on the result. As it is a huge dataset I prefer to have it in one query instead scripting with PHP or so row by row.
The pseudocode could look like follows:
SELECT status FROM First WHERE userid=.... ;
IF 'status' = 2 THEN INSERT INTO Second (...)
ELSE INSERT INTO Third (...);
It can be converted to the form:
SELECT Count(*) AS cnt FROM First WHERE status=2 AND userid=.... ;
IF #cnt>0 INSERT INTO Second (...)
ELSE INSERT INTO Third (...);
The problem is that MySQL seems to not see the value of #cnt nor there is IF...ELSE... statement in MySQL for queries as far as I know (I may be wrong).
You may use 2 queries:
INSERT INTO Second ( {columns to be inserted into} )
SELECT {values to be inserted}
WHERE EXISTS (
SELECT status
FROM First
WHERE userid=....
AND status = 2
);
INSERT INTO Third ( {columns to be inserted into} )
SELECT {values to be inserted}
WHERE NOT EXISTS (
SELECT status
FROM First
WHERE userid=....
AND status = 2
);
Or use stored procedure.

How to ignore consecutive duplicates on insert statement in MySQL

I want to ignore duplicates (or update key on duplicates), but only on consecutive duplicates.
Say my initial table looks like this (uk and a are column names):
uk a
----
x 1
Iteration 1 inserts 1 so I want this to be ignored in order to avoid duplicates.
Iteration 2 inserts 2 and my table now looks like this:
uk a
----
x 1
x 2
Iteration 3 inserts 1 and because the last row where my unique key = x was different to 1 then I want 1 to be inserted again:
uk a
----
x 1
x 2
x 1
How can this be achieved in MySQL?
My current solution is to query in data from the table first and remove these duplicates, but I would prefer that it was handled by MySQL.
You need a column that will be an auto-increment primary key
CREATE TABLE your_table(
id INT NOT NULL AUTO_INCREMENT,
uk CHAR(30) NOT NULL,
a INT,
PRIMARY KEY (id)
);
INSERT INTO your_table(uk, a) VALUES ('x', 1)
now you can use the following insert command to avoid duplicates as you describe it
INSERT INTO your_table(uk, a)
SELECT 'x', 1 FROM your_table t1
JOIN (
SELECT max(id) maxid, uk
FROM your_table
GROUP BY uk
) t ON t.maxid = t1.id and
t1.a != 1 and
t.uk = 'x'
The second insert can be the following
INSERT INTO your_table(uk, a)
SELECT 'x', 2 FROM your_table t1
JOIN (
SELECT max(id) maxid, uk
FROM your_table
GROUP BY uk
) t ON t.maxid = t1.id and
t1.a != 2 and
t.uk = 'x'
The third insert will be the same as the first one and the result table will be as expected.
See the demo
From your table it is not visible, which values got inserted last. Data in a table is considered unordered. So for your last example we know there are the three records x|1, x|1, x|2 in the table, but not whether x|1 or x|2 was inserted last. You'd need an additional column to indicate this. This could be a datetime or an ascending ID.
If you don't want to change your table, you need a helper table containing the last record instead. Anyway, you'd write a before-insert trigger to look up the last inserted value and throw an error when the new record matches the last inserted record for th uk.
create table mytable(uk char(1), a int);
create table mytable_helper(uk char(1), a int, primary key (uk));
create trigger mytable_ins BEFORE INSERT ON mytable FOR EACH ROW
begin
DECLARE msg VARCHAR(128);
if exists (select * from mytable_helper h where new.uk = h.uk and new.a = h.a) then
set msg = concat('Consecutive duplicate for a = ', new.a, ' and uk = ''', new.uk, '''.');
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = msg;
else
replace into mytable_helper (uk, a) values (new.uk, new.a);
end if;
end;
insert into mytable (uk, a) values ('x', 1);
insert into mytable (uk, a) values ('x', 2);
insert into mytable (uk, a) values ('x', 1);
insert into mytable (uk, a) values ('y', 3);
insert into mytable (uk, a) values ('x', 1);
Error(s), warning(s):
Consecutive duplicate for a = 1 and uk = 'x'.
REXTESTER http://rextester.com/XOG65602

Compare large MySQL tables

I need to make a comparison between two (or more) tables with around 60.000 rows and about 60 columns.
In these tables there are two values on which I want to run a query. The purpose of the query is to count the rows which exists in TABLE_A but don't exist in TABLE_B based on two values in the row.
I've ran the following query:
SELECT id
FROM table_a ta
WHERE NOT EXISTS (
SELECT id
FROM table_b tb
WHERE ta.value1=tb.value1 AND ta.value2=tb.value2
)
As said, I've tried the code above and some variations on it. But to run this query it takes ages before it's finished. I hope to find a solution which runs in under 10 seconds.
Next query I tried, and of which I thought was working:
SELECT value1, value2
FROM (
SELECT ta.value1, ta.value2
FROM table_a ta
UNION ALL
SELECT tb.value1, tb.value2
FROM table_b tb
) result
GROUP BY value1, value2
HAVING COUNT(*) = 1
ORDER BY value1
The code shows me all differences between the two tables. So if valueX exists in TABLE_A but not in TABLE_B it's shown and vice versa.
So in short, I want to get all rows from TABLE_A which are not present in TABLE_B based on two values in the row.
Hope someone can help, thanks!
Why not use a join?
/* Create a table called NAMES */
CREATE TABLE NAMES(Id integer PRIMARY KEY, Name text, LastName text);
CREATE TABLE OTHERNAMES(Id integer PRIMARY KEY, Name text, LastName text);
/* Create few records in this table */
INSERT INTO NAMES VALUES(1,'Tom','Riddle');
INSERT INTO NAMES VALUES(2,'Lucy','I love');
INSERT INTO NAMES VALUES(3,'Frank','Frankly');
INSERT INTO NAMES VALUES(4,'Jane','Austen');
INSERT INTO NAMES VALUES(5,'Robert','Downey');
INSERT INTO OTHERNAMES VALUES(2,'Lucy','I love');
INSERT INTO OTHERNAMES VALUES(3,'Frank','Frankly');
INSERT INTO OTHERNAMES VALUES(4,'Jane','Austen');
INSERT INTO OTHERNAMES VALUES(5,'Robert','Downey');
select * from NAMES
LEFT JOIN OTHERNAMES on
NAMES.Name = OTHERNAMES.Name
AND Names.LastName = OTHERNAMES.LastName
where OTHERNAMES.id is null
See it online http://sqlfiddle.com/#!9/640c53/1
If you use a LEFT JOIN Items that don't exist in the right table will be replaced with null entries, which can be filtered with a where.
I don't know how efficient that is with your 60.000 database but this usually does the trick for me.
After some trial and error I have improved the second block of code. I noticed an additional field in my table which I could use to further filter the results.
SELECT date, value1, value2
FROM (
SELECT date, value1, value2
FROM (
SELECT ta.date, ta.value1, ta.value2
FROM table_1 ta
UNION ALL
SELECT tb.date, tb.value1, tb.value2
FROM table_2 tb
) filter
GROUP BY value1, value2
HAVING COUNT(*) = 1
) result
WHERE date='YYYY-MM-DD'
This code filters the results in under 4 seconds.
Anyway, thanks everyone for the trouble.

How can i get values from 3 different columns into single column in another table

select cons_id,teh_id,local_id,panchayt_id,war_id,ha_id from b...;
select rep_value_id from val;`
i need to get the above values into single column in another table.
how can i solve it by a query or using stored procedure.
You can do something like this in oracle sql .
Insert into VAL_TABLE (ID,COMMON_FIELD) values (VAL_TABLE_ID.nextval, ( SELECT CONS_ID || TECH_ID || LOCAL_ID from TABLE_B));
Or in MySQL
Insert into VAL_TABLE (ID,COMMON_FIELD) values (1, ( SELECT concat( id, type, details) from TABLE_B ) );
Try this...
UPDATE my_table SET col1=
(SELECT CONCAT_WS(',',val.rep_value_id,cons_id,teh_id,local_id,panchayt_id,war_id,ha_id)
FROM b,val);

mysql insert value if it doesn't exist

I'm trying to insert an ingredient to an ingredients table if it doesn't exist.
I'm using the following syntax:
INSERT INTO ingredient(Name)
(
SELECT 'ingName' FROM dummytable WHERE
(SELECT count(*) FROM ingredient WHERE Name = 'ingName')=0)
This does not seem to work (0 rows affected), even though the SELECT query seem to return the desired result (an entry which contains "ingName").
The "ingredient" table has 2 columns: Name, id (id is auto incremented)
Thanks,
Li
Its better to add unique index on the name column:
ALTER TABLE `ingredient` ADD UNIQUE(`Name`)
After doing that you can use INSERT IGNORE:
INSERT IGNORE INTO `ingredient` ... /* anything */
That's because your inner query SELECT count(*) FROM ingredient WHERE Name = 'ingName' is returning a value > 0 and hence the upper query SELECT 'ingName' FROM dummytable WHERE is not selecting any rows and so no insert is happening.
I tried the same with a test table having 2 column name|value and it did worked fine
INSERT INTO test1(name) (
SELECT 'name' FROM test2 WHERE
(
SELECT count(*) FROM test2 WHERE name = 'bilboa'
)
=0
)
Inserted 2 rows with value name cause that's what I am selecting in select query and my test table 2 rows.