I'm no MySQL guru.
I'm trying to update a table clients.converted from projects.last_update column.
DATETIME: clients.converted (new column as of now).
DATETIME: projects.last_update.
BOOLEAN: projects.converted.
For each client's project, there is the possibility to end the project with a prospect-to-client conversion, if so, (boolean) projects.converted will me TRUE.
What I want is to do an UPDATE statement on clients to fill clients.converted from MAX(projects.last_update) WHERE project's projects.converted = true.
So far I have tried a couple of queries, but this one grasps the idea in a less-confusing way:
UPDATE clients AS `Client`
INNER JOIN projects AS `Project` ON Project.client_id = Client.id
SET Client.converted = MAX(Project.last_update)
WHERE Project.converted = TRUE;
But it's not working (because I can't use MAX function directly on assignment) and I've run out of ideas on how to do an UPDATE with JOINS using the MAX function applied to a DATETIME column.
I did a SELECT statement to gather the information I need first and
it works like a charm:
SELECT Client.id, count(*), MAX(Project.last_update) FROM projects AS `Project`
LEFT JOIN clients AS `Client` ON Client.id = Project.client_id
WHERE Project.converted = TRUE
GROUP BY Client.id;
Any help is very much appreciated!
Thanks in advance.
MAX is an aggregate function, which means it cannot (or rather, generally should not) be used without a GROUP BY; you'll need to use a subquery.
UPDATE clients AS `Client`
INNER JOIN (SELECT client_id, MAX(last_update) AS max_lu
FROM projects
WHERE converted = TRUE
GROUP BY client_id
) AS `Project` ON Project.client_id = Client.id
SET Client.converted = Project.max_lu
;
Related
Good day,
I have a small issue with MySQL Distinct.
Trying the following query in my system :
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`, `bookingcomment_message` FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791
The point is that there are bookings like 29791 that have many comments added.
Let's say 10. Then when running the above query I see 10 results instead of one.
And that's not the way DISTINCT supposes to work.
I simply want to know if there are any comments. If the comment ID is not 0 then there is a comment. Of course I can add COUNT(blabla) as comment_number but that's a whole different story. For me now I'd like just to have this syntax right.
You may try aggregating here, to find which bookings have at least a single comment associated with them:
SELECT
b.booking_id,
b.booking_ticket,
b.booking_price
FROM mysystem_booking b
LEFT JOIN mysystem_bookingcomment bc
ON b.booking_id = bc.bookingcomment_link
WHERE
b.booking_id = 29791
GROUP BY
b.booking_id
HAVING
COUNT(bc.bookingcomment_link) > 0;
Note that depending on your MySQL server mode, you might have to also add the booking_ticket and booking_price columns to the GROUP BY clause to get the above query to run.
You can try below - using a case when expression
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`,
case when `bookingcomment_message`<>'0' then 'No' else 'Yes' end as comments
FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791
I have two tables, communication(that has a column timestamp,FromIDNumber and FromX ) and commLocation(that has a column timestamp,FromIDNumber and x).
I want to set communication.FromX = commLocation.x when the two tables have the same timestamp and FromIDNumber.
I tried doing this:
UPDATE communication
SET FromX=(SELECT commLocation.x
FROM commLocation
JOIN communication
ON communication.Timestamp=commLocation.timestamp
WHERE communication.FromIDNumber=commLocation.FromIDNumber);
But I got an error:
You can't specify target table 'communication' for update in FROM clause
How would I accomplish this? This is the SQL Fiddle for it. Right now, I'm inserting the FromX values at the end of the table, and I don't want that because I need it to correspond to a certain row of communication.... how would I do this?
Any help would be greatly appreciated, thanks!!
You can do a JOIN operation in an UPDATE statement.
For example:
UPDATE communication c
JOIN commLocation l
ON l.timestamp = c.timestamp
AND l.fromidnumber = c.fromidnumber
SET c.fromx = l.x
This assumes that (timestamp,fromidnumber) is unique in commLocation.
For developing a query like this, we usually start with a SELECT statement...
SELECT c.timestamp
, c.fromidnumber
, c.fromx AS old_fromx
, l.x AS new_fromx
FROM communication c
JOIN commLocation l
ON l.timestamp = c.timestamp
AND l.fromidnumber = c.fromidnumber
The new_fromx in the SELECT is the expression/value we're going to assign to the column. We can return additional columns in the SELECT list, to verify the statement is doing what we want it to do.
Once we get that working, we convert that into an update by removing the SELECT ... FROM and replacing it with UPDATE. And adding a SET clause before the WHERE clause.
I am having a tough time figuring out how to do this update query. Basically I need to update a table named tblOpenJobs. It needs to be updated with the dbo_WorkOrders table with the Max Install date. But there is not direct relationship between those two tables you need to have the dbo_premise table between. Here is my query, what am I doing wrong?
UPDATE tblOpenJobs
INNER JOIN (dbo_Premise INNER JOIN dbo_WorkOrders w (WHERE w.InstallDate IN
(SELECT MAX(InstallDate) FROM dbo_WorkOrders WHERE dbo_WorkOrders.PremiseKey = w.PremiseKey))
ON (dbo_Premise.PremiseKey = w.PremiseKey)
ON tblOpenJobs.ServiceOrderNum = dbo_Premise.AccountNumber
SET tblOpenJobs.InstallerID = w.InstallerID,
tblOpenJobs.InstallDate= w.InstallDate,
tblOpenJobs.New_Serial_num= w.NewSerial,
tblOpenJobs.Old_Reading= w.OldRead;
I checked this in Access 2007 query window:
Your query seems neither Transact-SQL, neither Access, as the two have different syntax.
In Access, table aliasing must use the keyword AS, while Transact-SQL does not require:
UPDATE ((tblOpenJobs
INNER JOIN dbo_Premise
ON tblOpenJobs.ServiceOrderNum = dbo_Premise.AccountNumber)
INNER JOIN dbo_WorkOrders AS w
ON dbo_Premise.PremiseKey = w.PremiseKey)
SET tblOpenJobs.InstallerID = w.InstallerID,
tblOpenJobs.InstallDate = w.InstallDate,
tblOpenJobs.New_Serial_num = w.NewSerial,
tblOpenJobs.Old_Reading = w.OldRead
WHERE (w.InstallDate IN
(SELECT MAX(InstallDate)
FROM dbo_WorkOrders
WHERE dbo_WorkOrders.PremiseKey = w.PremiseKey))
This is correct in syntax, but I'm not sure it can update your data, as multi-table linked update is not easy in Access.
I have a query in MySQL and I am making a crystal report by using this.
Now inside the query i have a column called scan_mode and it is coming from gfi_transaction table. This scan_mode I am using in report to suppress some sections. But some times this value is coming null for some transaction ids.
So now I want to take this scan_mode as separate query so that it will work.
Can any one please help how I can modify the below query to take only scan_mode column.
SELECT
cc.cost_center_code AS cccde,
cc.name AS ccnme,gf.scan_mode,
cc.cost_center_id AS ccid,
site.name AS siteme,
crncy.currency_locale AS currency_locale,
cntry.language AS LANGUAGE,
cntry.country_name AS cntrynm,
crncy.decimal_digits AS rnd,
gf.transaction_no AS Serial_No,
brnd.name AS brand_name,
rsn.description AS reason,
gf.comment AS COMMENT,
ts.status_description AS STATUS,
DATE_FORMAT(gf.created_date,'%d/%m/%Y') AS created_date,
gf.created_by AS created_by,
IFNULL(gf.approval_no,'Not authorized') AS Trans_no,
gf.approved_date AS approval_dt,
gf.approved_by AS approved_by,gf.status AS status1,
IFNULL(loc.cost_center_code,cc.cost_center_code) AS cur_location,
gf.document_ref_no,gf.document_ref_type,
,DATE_FORMAT(document_ref_date1,'%d/%m/%Y')) AS invoice_no
FROM
gfi_transaction gf
INNER JOIN gfi_instruction gfn ON (gf.transaction_id=gfn.transaction_id)
INNER JOIN gfi_document_instruction doc ON (gf.ref_transaction_no = doc.document_instruction_id)
INNER JOIN reason rsn ON (gf.reason_id = rsn.reason_id)
INNER JOIN gfi_status ts ON (gf.status = ts.gfi_status_id)
INNER JOIN transaction_type tt ON (gf.transaction_type_id = tt.transaction_type_id)
INNER JOIN brand brnd ON(gf.brand_id=brnd.brand_id)
-- cc details
INNER JOIN cost_center cc ON (brnd.parent_brand = cc.brand_id OR gf.brand_id = cc.brand_id)
INNER JOIN site site ON(cc.site_id = site.site_id)
INNER JOIN country cntry ON (site.country_id = cntry.country_id)
INNER JOIN currency crncy ON (cntry.currency_id=crncy.currency_id)
LEFT OUTER JOIN alshaya_location_details loc ON
(gf.brand_id = loc.brand_id AND loc.cost_center_id = gf.cost_centre_id)
LEFT OUTER JOIN alshaya_location_details locto ON
(locto.cost_center_id = gf.from_cost_center_id)
WHERE
gf.transaction_id='{?TransID}'
AND rsn.transaction_type_id IN (10,11,14)
wow, that's a big query. I ran across a similar problem in a query i was building and found the if syntax to be a solution to my problem. This was also answered in this question: MYSQL SELECT WITHIN IF Statement
$psdb->query = "SELECT count, s.classid,
if (k.sic != k.siccode, k.siccode, s.siccode) as siccode,
if (k.sic != k.siccode, k.sicdesc, s.sicdesc) as sicdesc,
if (k.sic != k.siccode, k.sicslug, s.sicslug) as sicslug
FROM ...
It looks like scan_mode column comes from "gfi_transaction" table which seems to be primary table in your query. If you get null for this column then it means your table itself have NULL value for this column. Taking that separately in a query wont solve your problem. Try replacing null with a default value and handle it in code. You can add default value instead of NULL by using ifnull(scan_mode, 'default')
I'm just getting started with Propel. I have a situation where I am left joining a table to itself to obtain a min value. I have the query written that works as I need it to, but I can't figure out how to do it using the Propel models.
This query gets the first successful payment made by each user that registered after a given date:
SELECT `p`.`id` AS `payment_id`,
`p`.`request_date`,
`u`.`id` AS `user_id`,
`u`.`registration_date`
FROM `payments` AS `p`
LEFT JOIN `payments` AS `filter`
ON `p`.`user_id` = `filter`.`user_id`
AND `p`.`id` > `filter`.`id`
INNER JOIN `users` AS `u`
ON `p`.`user_id` = `u`.`id`
AND `u`.`registration_date` >= '2013-07-28'
WHERE `p`.`completed` = 1
AND `filter`.`id` IS NULL
ORDER BY `u`.`registration_date` DESC
Please help me translate that to Propel code.
Try this:
<?php
$q = \PaymentsQuery::create();
$q->select(array('Payments.RequestDate', 'Users.RegistrationDate'));
$q->withColumn('Payments.Id', 'payment_id');
$q->withColumn('Users.Id', 'user_id');
$q->withAlias('Filter', \PaymentsPeer::TABLE_NAME);
// The object to join must ALWAYS be on the right side
$q->addJoin(\PaymentsPeer::USER_ID, \PaymentsPeer::alias('Filter', \PaymentsPeer::USER_ID), \ModelCriteria::LEFT_JOIN);
$q->addJoin(\PaymentsPeer::USER_ID, \UsersPeer::ID, \ModelCriteria::INNER_JOIN);
$q->where('Payments.Id > Filter.Id');
$q->where('User.RegistrationDate >= ?', '2013-07-28');
$q->where('Payments.Completed = ?', 1);
$q->where('Filter.Id IS NULL');
$q->orderBy(\UsersPeer::REGISTRATION_DATE, \ModelCriteria::DESC);
I want to use the add method for having columns equal each other, but this cannot be done because it will convert the second column into a string. I've asked this on the Propel Users Google Group with no response so far. Therefore, I'm not sure if the first and fourth where clauses will work.