Find duplicates for combination of two columns in a MySQL database - mysql

I work on a dataset with three different columns: pile, position and info.
There is no duplicate in the database, but it can happen, that for one combination of pile and position there is one or two different texts in the info column. And those are the entries I tried to find.
I tried the following
SELECT COUNT(DISTINCT(`pile`, `position`)) FROM db;
But received an error message
ERROR 1241 (21000): Operand should contain 1 column(s)
Is there a way to find distinct combinations of values in two columns?

This works even without subselects.
SELECT
`pile`,
`position`,
COUNT(*) AS c
FROM
db
GROUP BY
`pile`,
`position`
HAVING c > 1;
The command above shows all combinations of pile and position that occur more than once in the table db.

To get the count of distinct duplicates (group by used in preference here)
select count(*)
from (
select pile, position
from db
group by pile, position
) x
To find the actual duplicate records
select db.*
from (
select pile, position
from db
group by pile, position
having count(*) > 1
) x
join db on db.pile = x.pile and db.position = x.position

SELECT *
FROM db x
WHERE EXISTS (
SELECT 1 FROM db y
WHERE y.pile = x.pile
AND y.position =x.postion
AND y.other_field <> x.other_field
);
Now, for other_field you can use some unique id column, or any combination of fields (except for {pole, postion} of course)

Related

Need assistance with SQL Query with error message Operand should contain 1 column(s)

Good Day
I have the following query but I'm getting an error message 'Operand should contain 1 column(s)'
Any assistance would be greatly appreciated
UPDATE expenditure
SET BP = (
SELECT * ,
SUM(balance_provision - actual_amt_voucher) over (partition by voteid order by expenditureid) AS BalanceProvision
FROM expenditure
)
It looks like you want to update column bp with a window sum.
Your query fails because you are trying to assign a resultset (that has multiple columns) to a single column.
But even you were returning a scalar value from the subquery, this would not work, since MySQL does not allow reusing the target table of the update in a subquery.
Instead, yo can use the update ... join syntax. Assuming that expenditureid is the primary key of the table, as its name suggests, that would be:
update expenditure e
inner join (
select
expenditureid,
sum(balance_provision - actual_amt_voucher) over (partition by voteid order by expenditureid) bp
from expenditure
group by expenditureid
) e1 on e.expenditureid = e1.expenditureid
set e.bp = e1.bp

Getting an Operand should contain 1 column(s) error when merging values of two tables

I'll try to explain it the best I can. My English is not very good.
I want to combine values from two tables. It works fine when I only merge one table, like so:
SELECT `friendid`,`friendname`, (SELECT `islogged` FROM `account_data` WHERE `guildcard` = `friendid` ) FROM `guild_data` WHERE `accountid` = '42000007' ORDER BY `friendid` DESC LIMIT 0, 40
But I need two entries from the "account_data" table. I thought I could do it like this:
SELECT `friendid`,`friendname`, (SELECT `islogged`,`lastonline` FROM `account_data` WHERE `guildcard` = `friendid` ) FROM `guild_data` WHERE `accountid` = '42000007' ORDER BY `friendid` DESC LIMIT 0, 40
But apparently that isn't correct, and it throws me an error, namely:
[Err] 1241 - Operand should contain 1 column(s)
How can I make this work with 2 columns? Both values should be taken from the row with the guildcard value found from friendid.
Hope I've been clear enough.
It looks like you need to use a JOIN. Try this:
SELECT g.friendid, g.friendname, a.islogged, a.lastonline
FROM guild_data g
LEFT OUTER JOIN account_data a
ON g.friendid = a.guildcard
WHERE g.accountid = '42000007'
ORDER BY g.friendid DESC LIMIT 0, 40
Using a LEFT OUTER JOIN will ensure that you get results in guild_data that don't have rows in account_data. If you know that you will always have a corresponding row in account_data or if you want to exclude rows in guild_data that don't map to anything in account_data, use INNER JOIN instead.
If this doesn't give you the results you want, please let us know what is wrong with it. Post what you got with this query and what you expected to get.

The query gives single row query returns more than one row

I'm trying to show staff_code, staff_name and dept_name for those who have taken one book.
Here's my query:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME,BT.BOOK_CODE
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM,BOOK_TRANSACTIONS BT
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE = (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
It gives the error:
single-row subquery returns more than one row.
How to solve this?
Change = to IN:
WHERE SM.STAFF_CODE IN (SELECT ...)
Because the select returns multiple values, using equals won't work, but IN returns true if any of the values in a list match. The list can be a hard-coded CSV list, or a select with one column like your query is.
That will fix the error, but you also need to remove BOOK_TRANSACTIONS from the table list and remove BOOK_CODE from the select list.
After making these changes, your query would look like this:
SELECT SM.STAFF_CODE,SM.STAFF_NAME,DM.DEPT_NAME
FROM STAFF_MASTER SM,DEPARTMENT_MASTER DM
WHERE SM.DEPT_CODE =DM.DEPT_CODE
AND SM.STAFF_CODE IN (
SELECT STAFF_CODE
FROM BOOK_TRANSACTIONS
HAVING COUNT(*) > 1
GROUP BY STAFF_CODE)
I recommend learning the modern (now over 25 year old) JOIN syntax.

Retrieving rows that have 2 columns matching and 1 different

Below is my table called 'datapoints'. I am trying to retrieve instances where there are different instances of 'sensorValue' for the same 'timeOfReading' and 'sensorNumber'.
For example:
sensorNumber sensorValue timeOfReading
5 5 6
5 5 6
5 6 10 <----same time/sensor diff value!
5 7 10 <----same time/sensor diff value!
Should output: sensorNumber:5, timeOfReading: 10 as a result.
I understand this is a duplicate question, in fact I have one of the links provided below for references - however none of the solutions are working as my query simply never ends.
Below is my SQL code:
SELECT table1.sensorNumber, table1.timeOfReading
FROM datapoints table1
WHERE (SELECT COUNT(*)
FROM datapoints table2
WHERE table1.sensorNumber = table2.sensorNumber
AND table1.timeOfReading = table1.timeOfReading
AND table1.sensorValue != table2.sensorValue) > 1
AND table1.timeOfReading < 20;
Notice I have placed a bound for timeOfReading as low as 20. I also tried setting a bound for both table1 and table 2 as well but the query just runs until timeout without displaying results no matter what I put...
The database contains about 700mb of data, so I do not think I can just run this on the entire DB in a reasonable amount of time, I am wondering if this is the culprit?
If so how could I properly limit my query to run a search efficiently? If not what am doing wrong that this is not working?
Select rows having 2 columns equal value
EDIT:
Error Code: 2013. Lost connection to MySQL server during query 600.000 sec
When I try to run the query again I get this error unless I restart
Error Code: 2006. MySQL server has gone away 0.000 sec
You can use a self-JOIN to match related rows in the same table.
SELECT DISTINCT t1.sensorNumber, t1.timeOfReading
FROM datapoints AS t1
JOIN datapoints AS t2
ON t1.sensorNumber = t2.sensorNumber
AND t1.timeOfReading = t2.timeOfReading
AND t1.sensorValue != t2.sensorValue
WHERE t1.timeOfReading < 20
DEMO
To improve performance, make sure you have a composite index on sensorNumber and timeOfReading:
CREATE INDEX ix_sn_tr on datapoints (sensorNumber, timeOfReading);
I think you have missed a condition. Add a not condition also to retrieve only instances with different values.
SELECT *
FROM new_table a
WHERE EXISTS (SELECT * FROM new_table b
WHERE a.num = b.num
AND a.timeRead = b.timeRead
AND a.value != b.value);
you can try this query
select testTable.* from testTable inner join (
SELECT sensorNumber,timeOfReading
FROM testTable
group by sensorNumber , timeOfReading having Count(distinct sensorValue) > 1) t
on
t.sensorNumber = testTable.sensorNumber and t.timeOfReading = testTable.timeOfReading;
here is sqlFiddle
This query will return the sensorNumber and the timeOfReading where there are different values of sensorValue:
select sensorNumber, timeOfReading
from tablename
group by sensorNumber, timeOfReading
having count(distinct sensorValue)>1
and this will return the actual records:
select t.*
from
tablename t inner join (
select sensorNumber, timeOfReading
from tablename
group by sensorNumber, timeOfReading
having count(distinct sensorValue)>1
) d on t.sensorNumber=d.sensorNumber and t.timeOfReading=d.timeOfReading
I would suggest you to add an index on sensorNumber, timeOfReading
alter table tablename add index idx_sensor_time (sensorNumber, timeOfReading)

Why am i getting "Subquery returns more than 1 row"

Hi I am making a webrowser game and I am trying to get monsters into my data base when I get the error:
Subquery returns more then 1 row
here is my code
INSERT INTO monster_stats(monster_id,stat_id,value)
VALUES
( (SELECT id FROM monsters WHERE name = 'Necroborg!'),
(SELECT id FROM stats WHERE short_name = 'atk'),
2);
any ideas how to fix this problem?
Try use LIMIT 1
INSERT INTO monster_stats(monster_id,stat_id,value) VALUES ((SELECT id FROM monsters WHERE name = 'Necroborg!' LIMIT 1),(SELECT id FROM stats WHERE short_name = 'atk' LIMIT 1),2);
Or you could use Insert from select, with join, if you have relations with 2 tables.
INSERT INTO monster_stats(monster_id,stat_id,value)
(SELECT monsters.id, stats.id, 2 as value FROM monsters
LEFT JOIN stats on monsters.id = stats.monsters_id
WHERE monsters.name = 'Necroborg!'
AND stats.short_name = 'atk'
)
MYSQL insert from select:
http://dev.mysql.com/doc/refman/5.1/en/insert-select.html
The problem is one or both of the following:
There is more than one monster named 'Necroborg!'.
There is more than on stat named 'atk'.
You need to decide what you want to do. One option (mentioned elsewhere) is to use limit 1 to get only one value from each statement.
A second option is to better specify the where clause so you get only one row from each table.
Another is to insert all combinations. You would do this with insert . . . select and a cross join:
INSERT INTO monster_stats(monster_id, stat_id, value)
SELECT m.id, s.id, 2
FROM (SELECT id FROM monsters WHERE name = 'Necroborg!') m CROSS JOIN
(SELECT id FROM stats WHERE short_name = 'atk');
A third possibility is that there is a field connecting the two tables, such as monster_id. But, based on the names of the tables, I don't think that is true.