SQL Duplicate entry for key 1 - mysql

I've recently had to take over the management of a database (within a school) that records certain stats, at the start of each year these stats are supposed to be reset.
I've been given a piece of code to run to reset these stats, however it is throwing out a 'Duplicate entry '10172-0' for key 1 error when I try to run it. (the '10172-0' part also happens on various other numbers/student_id's). The code I've been given is:
Insert into cfc.student_stats (students_id, no_cfcs)
Select student_id, 0
from roombookings.students
where student_id >= 1
and student_id <= 15635
I've checked and there aren't duplicate entries when I check out the various student_id's so I'm at a loss with what to do. Underneath the error message I get a button to 'Browse' which then tells me the following:
Error
SQL query: Documentation
SELECT *
FROM
WHERE CONCAT_WS( "-", students_id, no_cfcs ) = "10172-0"
ORDER BY students_id, no_cfcs
MySQL said: Documentation
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE CONCAT_WS("-", students_id, no_cfcs)
= "10172-0"' at line 3
I've had a browse through lots of other similar problems on here but none of them seemed to match up with what I was getting (but I don't really understand SQL). Any help appreciated, cheers!

You are doing this
SELECT *
FROM
WHERE
in above query you missed to add table name.
Edit
SELECT *
FROM
roombookings.students
WHERE

Regarding that second error, I'm not sure why you don't just use:
WHERE students_id = 10172 AND no_cfcs = 0
It seems a bit silly and inefficient to turn them into strings just to compare them.
In addition, it appears you haven't selected an actual table to read from, so something like this would be better:
SELECT *
FROM cfc.student_stats
WHERE students_id = 10172
AND no_cfcs = 0
There's also no point ordering by students_id, no_cfcs when you're only allowing one possibility for each, so I removed that bit.
Regarding your first error, I suspect that may be because of duplicate entries in the roombookings.students table. If you do:
select student_id, count(*)
from roombooking.students
where student_id >= 1 and student_id <= 15635
group by student_id
and the second column has any number greater than one in it, you'll get an error trying to insert duplicates into the cfc.student_stats table.
That's because for each student_id in that roombooking.students table, you'll try to create one in the cfc.student_stats table with a primary key made up of the student ID and the constant 0.
If you don't get any counts greater than one, then it's most likely that there's already a row in the cfc.student_stats table with that student ID.

Related

How to delete rows in a mySQL table specified by data from the same table (in one expression)? [duplicate]

This question already has answers here:
MySQL Error 1093 - Can't specify target table for update in FROM clause
(16 answers)
Closed 4 years ago.
I want to delete rows from a table "Book", where two colums have appeared before.
I successfully selected the ids of the rows wich should be deleted like so:
SELECT all_dupes.book_id
FROM (SELECT *
FROM Book as BBook NATURAL JOIN Book as BBBook
WHERE book_id NOT IN (SELECT book_id
FROM Book as BBook NATURAL JOIN Book as BBBook
GROUP BY buying_price,
selling_price
HAVING Count(*) = 1
ORDER BY book_id)
ORDER BY book_id) AS all_dupes
WHERE book_id NOT IN (SELECT book_id
FROM Book as BBook NATURAL JOIN Book as BBBook
GROUP BY buying_price,
selling_price
HAVING Count(*) >= 2
ORDER BY book_id);
…but when I try to delete the rows with
DELETE FROM Book
WHERE book_id IN (
<expression as above without tailing ;>
) ;
I get an error ERROR 1093 (HY000): Table 'Book' is specified twice, both as a target for 'DELETE' and as a separate source for data
I already tried to alias the table and to natural join the table to itself, like suggested in other questions regarding this issue.
Also I read quite some ammount of questions here, but they mostly are very specific and I don't get how to change my delete-query by the answers provided there.
What do I have to change in order to get this done? Splitting the expression is not an option (meaning there mustn't be two ;, but just one expression).
Database used: MariaDB
There are a few problems with your SQL. I would fix those first, even though your DBMS isn't rejecting the query. It might fix the problem, because in your DELETE statement you might have finally pushed the system past its limit. In any case it will clarify the question.
ORDER BY is, in standard SQL, permitted only once, in the outermost SELECT clause. It is a way to return the rows to the calling process in a particular order, not a way to express order internally to the SQL processor. Your extra ORDER BYs don't affect your query, so remove them.
GROUP BY should repeat any column names not aggregated in the SELECT clause. Because you select book_id, you should also group by book_id.
I doubt you actually need all those joins anyway. I'm not sure what you're trying to do, but I think your query might just be
delete Book
where exists ( select 1
from Book as B
where B.book_id = Book.book_id
group by B.book_id, B.buying_price, B.selling_price
having count(*) > 1
)
That would eliminate all rows with a book_id for which any combination of {book_id, buying_price, selling_price} is not unique. But I'm not sure that's what you really want.
I want to delete rows from a table "Book", where two colums have appeared before.
Yeah, there is no "before" in SQL, because there's no order. I think what you mean is that if you have 3 "duplicate" rows, you'd like to eliminate the extra 2. SQL has no such operation.
SQL operates by predicate logic: rows are deleted according to whether or not they match some criteria. Duplicate rows, by definition, all meet the same criteria. Because there's no order, there's no notion of deleting all those that match except the first one.
The best solution, it must be said, is to prevent duplication in the first place by correctly declaring uniqueness in the table definition. Failing that, the remedy is usually to insert the distinct set into a temporary table, delete in the main table all those that exist in the temporary one, insert from the temporary into the main, and drop the temporary table.

mysql sql weird issue?

return multiple data
why?
mysql sql :
select * from t_book where id=(select round(max(id)*rand()) from t_book)
As suggested by #Tarek you might have duplicated id values. To find out which you can run this query:
SELECT id, COUNT(*) c FROM t_book GROUP BY id HAVING c > 1;
On the assumption that "id" is a unique primary key value, it shouldnt return multiple values. In the returned values do all of the "id" fields match, or is it returning multiple varying ids?
You have a Syntax error,
The function Round takes the form:
ROUND(N,[D]);
The problem is not with your id column's uniqueness.
select round(max(id)*rand()) from t_book
This will return various number of ids, at least in mysql 5.6. I don't know why, but it's really weird.
You can try this, for selecting a random record from your table:
select * from t_book order by rand() limit 1;
If you stick with this round-max-random method, keep in mind that round can return 0 too and it's unlikely that you have a 0 id.
First I thought this is caused by duplicate id values. You can try this fiddle, and see what happens: http://sqlfiddle.com/#!9/7fc510/1.
For multiple runs I got 0, 1 or 2 result records.

mysql (innodb) select distinct + calculate values to copy in other table

I'm trying to combine some queries to (eventually) use them in a stored procedure because I'm afraid in the long run it will take some time to process due to calculating and I guess a datawarehouse makes faster lookups possible.
I came up with this, but I keep getting syntax error messages (#1064) (check the manual that corresponds to your MySQL server version for the right syntax to use near 'select distinct)
Does anyone know a nice aproach for this?
insert into datawarehouse (itemid,rating) values
(select distinct itemid from ratings),
(select sum(rating)/count(*)from ratings where itemid in (select distinct itemid from ratings))
If I run the inner select queries separately it works but combining it seems troublesome.
In a nutshell I want to retrieve (i) the distinct itemid from table ratings, (ii) perform some calculations on the rows of table ratings for each itemid
and copy those into table datawarehouse.
If anyone has an idea or a good read on this, I would love to hear it.
Use INSERT INTO ... SELECT and GROUP BY:
INSERT INTO datawarehouse (itemid, rating) SELECT itemid, sum(rating)/count(*) FROM ratings GROUP BY itemid

MySQL not respecting 'HAVING' where aliases are used?

I've got the following table structure:
CREATE TABLE reservations (
id int auto_increment primary key,
minDate date,
maxDate date
);
CREATE TABLE stays (
id int auto_increment primary key,
reservation_id int,
theDate date
);
INSERT INTO reservations VALUES (null, CURDATE(), CURDATE());
INSERT INTO stays VALUES (null, 1, CURDATE());
It's for a booking system that records reservations (a general container) and stays (someone for each night).
I try to run the following query to extract all reservations that have a different number of days in the database (e.g. the reservation says there should be 2 nights, but there's only 1 in the database, etc)
SELECT
reservations.id AS 'Reservation ID',
reservations.minDate,
reservations.maxDate,
DATEDIFF(reservations.maxDate, reservations.minDate) + 1 AS 'numNights',
COUNT(DISTINCT stays.id) AS 'numStays'
FROM
reservations
LEFT JOIN stays ON reservations.id = stays.reservation_id
GROUP BY
reservations.id
HAVING
`numNights` != `numStays`
ORDER BY
reservations.minDate
This works perfectly on my Windows version of MySQL (xampp), and production CentOS server, but is broken on a testing machine running version 5.6.19-0ubuntu0.14.04.1. On the broken machine, it's pulling back all rows, even though the numNights and numStays columns match.
If I replace the aliases in the HAVING clause with the expressions used in the SELECT part, then it works fine, but I can't understand why it doesn't like the aliases in the HAVING clause (on this version)?
Btw, it's definitely not a no-quote/quote/double-quote/backtick issue, I've tried all combinations. I might have thought it was a charset encoding issue, but DATEDIFF() and COUNT() should be returning the same type of integers back, right? And that wouldn't explain why expressions work in the HAVING part.
I have an SQL Fiddle set up for experimenting as well... it works fine on that too. So now I'm at a loss
This is a "wrong" SQL-Query, because of wrong GROUP BY. But unfortunately, this allowed mysql sometimes. Please check mySql Configuration ONLY_FULL_GROUP_BY and http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sqlmode_only_full_group_by
Both the tables contain only single row of data.Without 'Having' clause its returning only 1 row. sql fiddle. As numNights=numStays=1 , while executing 'Having' its giving nothing.I think it'll help you.

SQL statement working in MySQL not working in Postgresql - Sum & group_by rails 3

So I'm very new to working in SQL in general, let alone rails but I have this statement that works in MySQL:
portfolio_values.select("portfolio_values.*, SUM(portfolio_values.value) as totals").group("portfolio_values.day").map(&:totals)
But in postgresql is throws this error:
GError: ERROR: column "portfolio_values.id" must appear in the GROUP
BY clause or be used in an aggregate function : SELECT
portfolio_values.*, SUM(portfolio_values.value) as totals FROM
"portfolio_values" WHERE "portfolio_values"."user_id" = 3 GROUP BY
portfolio_values.day ActiveRecord::StatementInvalid: PGError: ERROR:
column "portfolio_values.id" must appear in the GROUP BY clause or be
used in an aggregate function
I just don't really understand what its saying I should be doing differently?
Since PostgreSQL 9.1 a primary key column in the GROUP BY list covers the whole table. Therefore, given that portfolio_values.id is, in fact, the primary key, you can simplify:
portfolio_values.select("portfolio_values.*, SUM(portfolio_values.value) as totals").group("portfolio_values.id").map(&:totals)
I quote the 9.1 release notes:
Allow non-GROUP BY columns in the query target list when the primary
key is specified in the GROUP BY clause (Peter Eisentraut)
The SQL standard allows this behavior, and because of the primary key,
the result is unambiguous.
However, in your case, this results in nonsense either way.
a. portfolio_values.id is the primary key.
Then SUM(portfolio_values.value) is pointless. There can only be one row per group.
b. portfolio_values.id is not the primary key.
Then you cannot include portfolio_values.* in the SELECT list.
If you wish to learn the meaning of * in a SELECT, start by reading the manual here.
You just have to add the portfolio_values.id column to the GROUP BY statement - like so:
portfolio_values.select("portfolio_values.*, SUM(portfolio_values.value) as totals").group("portfolio_values.id, portfolio_values.day").map(&:totals)
EDIT
While this is valid SQL, it's not a useful query - see other post.
You probably want distinct on:
http://www.postgresql.org/docs/9.1/static/sql-select.html#SQL-DISTINCT
Specifically something like:
select distinct on (yourdatefield) field1, field2, field3 from sometable;