I have a join table called carriers_rects that looks like this:
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| carrier_id | int(11) unsigned | NO | | NULL | |
| rect_id | int(11) unsigned | NO | | NULL | |
+------------+------------------+------+-----+---------+----------------+
I also have a rects table that looks like this:
+---------+-------------+------+-----+----------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+----------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(54) | NO | | new rect | |
| width | varchar(54) | NO | | NULL | |
| length | varchar(54) | NO | | NULL | |
| rounded | tinyint(1) | NO | | NULL | |
| xx | varchar(54) | NO | | NULL | |
| yy | varchar(54) | NO | | NULL | |
| height | varchar(54) | NO | | NULL | |
+---------+-------------+------+-----+----------+----------------+
I am trying to add a case_id column to rects and just make it a one-to-many relationship and kill the carriers_rects table. We are moving our DB and we never used the many-to-many relationship.
So I added the case_id column to rects:
alter table rects add case_id int(11) not null;
Then I tried to update the case_id on the rects with all the case_id's that would match from the carriers_rects table.
update rects set case_id = (select carrier_id from carriers_rects where rect_id = id);
I am getting column case_id cannot be null.
I tested to see if there where any nulls and I can't seem to find any.
select * from (select * from carriers_rects where rect_id IN(select id from rects)) `b` where id is null;
I also tried it the other way around because honestly I am a little confused.
select id from rects where id IN(select rect_id from carriers_rects)
Clearly I am not a sql genius. But would love to be schooled here.
Not sure why I am getting the error mentioned above.
What if you change to a update-join syntax rather than using subquery like
update rects r
join carriers_rects cr on cr.rect_id = r.id
set r.case_id = cr.carrier_id
where cr.carrier_id is not null;
The main reason of this error is in your inner query condition rect_id = id . They both are from carriers_rects (it means carriers_rects.rect_id = carriers_rects.id) so you get null. Change it to rect_id = rects.id
update rects set case_id =
(select carrier_id from carriers_rects where rect_id = rects.id);
Related
I have a nested query that deletes a row in table terms only if exactly one row in definitions.term_id is found. It works but it takes like 9 seconds on my system. Im looking to optimize the query.
DELETE FROM terms
WHERE id
IN(
SELECT term_id
FROM definitions
WHERE term_id = 1234
GROUP BY term_id
HAVING COUNT(term_id) = 1
)
The database is only about 4000 rows. If I separate the query into 2 independent queries, it takes about 0.1 each
terms
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| term | varchar(50) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
definitions
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| term_id | int(11) | YES | | NULL | |
| definition | varchar(500) | YES | | NULL | |
| example | varchar(500) | YES | | NULL | |
| submitter_name | varchar(50) | YES | | NULL | |
| approved | int(1) | YES | MUL | 0 | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
| votos | int(3) | NO | | NULL | |
+----------------+------------------+------+-----+---------+----------------+
To speed up the process, please consider creating an index on the relevant field:
CREATE INDEX term_id ON terms (term_id)
How about using correlated sub query using exists and try,
DELETE FROM terms t
WHERE id = 1234
AND EXISTS (SELECT 1
FROM definitions d
WHERE d.term_id = t.term_id
GROUP BY term_id
HAVING COUNT(term_id) = 1)
It's often quicker to create a new table retaining only the rows you wish to keep. That said, I'd probably write this as follows, and provide indexes as appropriate.
DELETE
FROM terms t
JOIN
( SELECT term_id
FROM definitions
WHERE term_id = 1234
GROUP
BY term_id
HAVING COUNT(*) = 1
) x
ON x.term_id = t.id
Hehe; this may be a kludgy way to do it:
DELETE ... WHERE id = ( SELECT ... )
but without any LIMIT or other constraints.
I'm depending on getting an error something like "subquery returned more than one row" in order to prevent the DELETE being performed if multiple rows match.
I have a simple table:
+-------------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| ID | bigint(20) | NO | PRI | NULL | |
| AdmissionDateTime | datetime | NO | | NULL | |
| AdmissionEvent | varchar(255) | YES | | NULL | |
| DischargeDateTime | datetime | YES | | NULL | |
| DischargeEvent | varchar(255) | YES | | NULL | |
| DemographicId | bigint(20) | NO | MUL | NULL | |
| FacilityId | bigint(20) | YES | MUL | NULL | |
| VisitId | bigint(20) | NO | MUL | NULL | |
| WardId | bigint(20) | NO | MUL | NULL | |
+-------------------+--------------+------+-----+---------+-------+
On which I run the following JPA (Spring-data) query:
#Query("SELECT w FROM WardTransaction w WHERE w.id = (SELECT MAX(x.id) FROM
WardTransaction x WHERE w = x AND w.visit = :visit)")
public WardTransaction findCurrent(#Param("visit") Visit visit);
On occasions I get the following exception.
org.springframework.dao.IncorrectResultSizeDataAccessException: More than one
result was returned from Query.getSingleResult(); nested exception is
javax.persistence.NonUniqueResultException: More than one result was returned from
Query.getSingleResult()
I have not been able to work out why this is happening. It does not seem to make a lot of sense to me as there can only be one 'MAX' - especially on Id (I have used 'admissionDate' in the past).
Any assistance appreciated.
why are you selecting table ? you should select columns .
try this
#Query("SELECT * FROM WardTransaction w WHERE w.id in (SELECT MAX(x.id)
FROM WardTransaction x WHERE w.id = x.id AND w.visit = :visit)")
This query is simpler and I think would get you what you want:
SELECT something
FROM sometable
Where something = someotherthing
ORDER BY sometable.id DESC
LIMIT 1
Basically it returns the results with the highest IDs at the top and grabs the first one.
I have this query
UPDATE trh_adminLoginDate SET superseded = true WHERE EXISTS
(SELECT * FROM trh_adminLoginDate AS a2 WHERE a2.adminId = a.adminId AND a2.loginDate > a.loginDate AND a2.clientPlatform = a.clientPlatform)
and table look like this.
+----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| dateCreated | datetime | NO | | NULL | |
| version | int(11) | NO | | NULL | |
| dateModified | datetime | NO | | NULL | |
| adminId | bigint(20) | NO | MUL | NULL | |
| clientPlatform | varchar(255) | YES | | NULL | |
| loginDate | datetime | YES | | NULL | |
| superseded | tinyint(1) | NO | | NULL | |
+----------------+--------------+------+-----+---------+----------------+
When I execute this query I get the below error:
ERROR 1093 (HY000): You can't specify target table 'a' for update in FROM clause
I can create temporary table and keep the result of the sub-query and then do the UPDATE. But I don't want to do in this way. Can someone suggest me better way of doing this?
You are using the alias "a" but you never define it.
Perhaps this would work:
UPDATE trh_adminLoginDate a
JOIN trh_adminLoginDate AS a2
ON a2.adminId = a.adminId
AND a2.loginDate > a.loginDate
AND a2.clientPlatform = a.clientPlatform
SET a.superseded = true
Or perhaps this will do the trick:
UPDATE trh_adminLoginDate a
SET superseded = true
WHERE EXISTS
(SELECT * FROM trh_adminLoginDate WHERE adminId = a.adminId AND loginDate > a.loginDate AND clientPlatform = a.clientPlatform)
I've been struggling with converting the following SQL to CDBCriteria to be used with a CActiveDataProvider:
"SELECT PresetDeviceLink., Device. FROM PresetDeviceLink INNER JOIN Device ON Device.id = PresetDeviceLink.deviceId WHERE Device.roomId = 1"
Table structure is as follows:
mysql> describe PresetDeviceLink;
+----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| presetId | int(11) | NO | | NULL | |
| deviceId | int(11) | NO | | NULL | |
| state | int(11) | NO | | 0 | |
| value | int(11) | NO | | 32 | |
+----------+---------+------+-----+---------+----------------+
mysql> describe Device;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| ref | int(11) | NO | | NULL | |
| roomId | int(11) | NO | | NULL | |
| typeId | int(11) | NO | | NULL | |
| paired | tinyint(1) | NO | | 0 | |
| name | varchar(255) | YES | | NULL | |
| description | text | YES | | NULL | |
| dimmerPos | int(11) | NO | | 0 | |
+-------------+--------------+------+-----+---------+----------------+
My code in my controller is as follows:
$criteria = new CDbCriteria;
$criteria->select = 'PresetDeviceLink.*, Device.*';
$criteria->join = 'INNER JOIN Device ON Device.id = PresetDeviceLink.deviceId';
$criteria->condition = 'Device.roomId = 1';
$presetDeviceLink=new CActiveDataProvider('PresetDeviceLink', array(
'criteria' => $criteria,
));
When run I get the following error:
CDbCommand failed to execute the SQL statement: SQLSTATE[42S22]: <b>Column not
found</b>: 1054 Unknown column 'PresetDeviceLink.deviceId' in 'on clause'. The SQL
statement executed was: SELECT COUNT(*) FROM `PresetDeviceLink` `t` INNER JOIN
Device ON Device.id = PresetDeviceLink.deviceId WHERE Device.roomId = 1
The strange thing is, If I use 'Device' as the CActiveDataProvider source and change the join statement to join to 'PresetDeviceLink', it then complains that the Device.roomId column could not be found.
Do I just not understand how CActiveDataProvider works? It looks to me that I can only use a condition (in a join or where clause) from a field in the table that I pass to the CActiveDataProvider. Any advice?
PS - the SQL query works beautifully in the MySQL console.
Thanks in advance,
Ben
As is visible in the "The SQL statement executed was:" line, the first table was aliased to t. This is Yii's standard behaviour.
As a result of this, you should use that alias to refer to that table instead of PresetDeviceLink. Or you could try setting $criteria->alias = 'PresetDeviceLink'; before using it in the CActiveDataProvider, though I have not personally tried that option, it should work.
I have the following tables:
pages:
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| page_id | int(11) | NO | PRI | NULL | auto_increment |
| type | varchar(20) | NO | | NULL | |
| categories | varchar(255) | NO | | NULL | |
| title | varchar(255) | NO | MUL | NULL | |
| text | longtext | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
custom:
+---------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| page_id | int(10) unsigned | NO | PRI | NULL | |
| key | varchar(255) | NO | PRI | NULL | |
| value | longtext | NO | | NULL | |
+---------+------------------+------+-----+---------+-------+
I want to join the tables in a way where:
1) all the entries from the first table are returned LEFT JOIN custom ON pages.page_id = custom.page_id
2) pages.type IN ('type_a', 'type_b', 'type_c')
3) "key" from the second table has value "votes" custom.key = 'votes'
I made everything so far, but the third condition is the problem. If there isn't entry for key = 'votes' in table custom the query returns only these with entries. I want to return NULL if missing entries.
I need key = 'votes', because I have other entries for this page_id where the key is not 'votes' and this duplicates the rows from pages
Simply add your contraint custom.key='votes' to the LEFT JOIN
SELECT *
FROM pages LEFT JOIN custom
ON pages.page_id=custom.page_id AND custom.key='votes'
WHERE pages.type IN('type_a','type_b','type_c') ;
I'd do it like this:
SELECT *
FROM pages
LEFT JOIN
( SELECT * From custom where key='votes') cv
on pages.page_id = cv.page_id
WHERE pages.type IN ('type_a', 'type_b', 'type_c');
try changing your where condition to custom.key = 'votes' OR custom.key is null.