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.
Related
I am stuck in 1 left join query in which I want to check multiple columns in on statement.
By default in the database, some column is null which I want to check in the on statement.
Now the issue is when I run a query using the OR operator it only runs the 1st condition and the rest are skipped.
If I use AND operator it throws an error.
So is there any way to get data from multiple conditions?
Here is my query:
$data = "SELECT
b.book_name, b.book_id,
b.cats_id, b.cats_id1,
b.cats_id2, b.cats_id3,
b.cats_id4, b.cats_id5,
b.cats_id6,
b.book_rating,
b.book_author,
b.book_stock,
b.book_publisher,
b.book_front_img,
b.book_status,
p.publisher_id,
p.publisher_name,
a.author_id,
a.author_name,
cat.cats_id,
cat.cats_name,
cat.cats_status
FROM
`books` AS b
LEFT JOIN `publisher` AS p
ON b.book_publisher = p.publisher_id
LEFT JOIN `author` AS a
ON b.book_author = a.author_id
LEFT JOIN categorys As cat
ON b.cats_id = cat.cats_id
OR b.cats_id1 = cat.cats_id
OR b.cats_id2 = cat.cats_id
OR b.cats_id3 = cat.cats_id
OR b.cats_id4 = cat.cats_id
OR b.cats_id5 = cat.cats_id
OR b.cats_id6 = cat.cats_id
GROUP BY
b.book_name
HAVING
cat.cats_name = '$search_data'
AND b.book_status = 1
ORDER BY
$sorting
LIMIT $offset, $page_limit"
You probably don't have more than one author displayed for your multi-author books either. You are misusing MySQL's notorious nonstandard extension to GROUP BY.
To troubleshoot this kind of query, disable that extension with SET sql_mode = CONCAT_WS(',',##sql_mode, 'ONLY_FULL_GROUP_BY'), then try your query again. You'll need more terms in your GROUP BY clause.
It looks like each books row has multiple category id columns. And it looks like you want to display information from your categorys table for each of them.
Use GROUP BY b.book_id, p.publisher_id, a.author_id, cats.cats_id to prevent MySQL's bizarro handling of GROUP BY from concealing your data.
I must add this: your multiple books.cats_id columns are not the SQLish way to handle your many-to-many relationship between books and categories. In the parlance of our trade, your books table is denormalized.
What you want is a new table called books_categorys with two columns, book_id and cats_id. It's called a join table. When a row is present in that table, it means a particular book is in a particular category. It's the SQLish way of handling a setup where each book can be in zero or more categorys. Here's an explanation. MySQL join many to many single row
Then you remove all the cats_id columns from books, and retrieve the categories like this.
Then you do something like this SELECT to get the categories.
SELECT books.id, books.name,
categorys.cats_id, categorys.cats_name, categorys.cats_status
FROM books
JOIN books_categorys ON books.book_id = books_categorys.book_id
JOIN categorys ON books_categorys.cats_id = categorys.cats_id
``
I'm trying to create a view in my relational MySQL database that will allow the user to update football match results from one (virtual) table within phpMyAdmin.
I have the view all setup visually how I want, and I am able to edit most of the fields, except I am getting error messages. If, for instance, I update the number of goals scored for a team, I get the following error messages shown below. It will still update that record, however, because if I refresh the page, that particular entry will change to what I entered.
I am aware that you cannot have a primary key on a view, but in terms of indexing, shouldn't the existing relationships be sufficient for this to work?
Another issue is updating the referee field. As this is a concatenated field (first_name + last_name), I cannot attempt to update it from the view.
This is my database structure:
This is the code for my view:
CREATE VIEW `view1_match_main` AS
SELECT
`match_main`.`match_id` AS `Match ID`,
`season`.`season` AS `Season`,
`match_status`.`status_no` AS `Status`,
`match_main`.`date_time` AS `Date`,
`c1`.`club_name` AS `Home Club`,
`mr1`.`goal` AS `Home Goals`,
`mr2`.`goal` AS `Away Goals`,
`c2`.`club_name` AS `Away Club`,
CONCAT(`referee`.`referee_first_name`,
' ',
`referee`.`referee_last_name`) AS `Referee`,
`stadium`.`stadium_name` AS `Stadium`,
`match_main`.`attendance` AS `Attendance`,
`match_main`.`bbc_url` AS `BBC URL`,
`match_main`.`sky_url` AS `Sky URL`
FROM
((((((((`match_main`
LEFT JOIN `referee` ON ((`match_main`.`referee_id` = `referee`.`referee_id`)))
LEFT JOIN `season` ON ((`match_main`.`season_id` = `season`.`season_id`)))
LEFT JOIN `match_status` ON ((`match_main`.`status_id` = `match_status`.`status_id`)))
LEFT JOIN `match_result` `mr1` ON (((`mr1`.`match_id` = `match_main`.`match_id`)
AND (`mr1`.`home_team` = 1))))
LEFT JOIN `club` `c1` ON ((`c1`.`club_id` = `mr1`.`club_id`)))
LEFT JOIN `match_result` `mr2` ON (((`mr2`.`match_id` = `match_main`.`match_id`)
AND (`mr2`.`home_team` = 0))))
LEFT JOIN `club` `c2` ON ((`c2`.`club_id` = `mr2`.`club_id`)))
LEFT JOIN `stadium` ON ((`c1`.`stadium_id` = `stadium`.`stadium_id`)))
ORDER BY `season`.`season` DESC , `match_main`.`date_time` , `c1`.`club_name`
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
;
Look the images, please.
The following query works great when is executed with the table 'participants':
SELECT
*
FROM
(SELECT
p.*, #curRow:=#curRow + 1 AS position
FROM
(SELECT #curRow:=0) r,
participants p
WHERE
(p.isVolunteer = 0
OR p.isVolunteer IS NULL)
GROUP BY p.id
ORDER BY p.lastRegistrationDate DESC
LIMIT 0 , 25) AS p
INNER JOIN
participants_registrations pr ON p.id = pr.participantId
INNER JOIN
registrations r ON pr.registrationId = r.id
ORDER BY p.position ASC , r.createdOn DESC
But, when I replace 'participants' by the view 'vparticipants' I cannot get the same result, that is suposed should be the same.
The problem is that the order of the results are different.
Using the table I get the rows ordered in descendant by createdOn column (date) and the position column with values starting from 1 to 25, but using the view 'vparticipants' I get the column 'position' starting from 6 to 30, and the order of column createdOn is in ascendant order. I need the same result as the table.
The view is very simple, it here:
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`#`localhost`
SQL SECURITY DEFINER
VIEW `vparticipants` AS
SELECT
`participants`.`id` AS `id`,
`participants`.`identificationNumber` AS `identificationNumber`,
`participants`.`firstName` AS `firstName`,
`participants`.`lastName` AS `lastName`,
`participants`.`email` AS `email`,
`participants`.`cellphone` AS `cellphone`,
`participants`.`city` AS `city`,
`participants`.`gender` AS `gender`,
`participants`.`shirtSize` AS `shirtSize`,
`participants`.`bloodType` AS `bloodType`,
`participants`.`emergencyContactName` AS `emergencyContactName`,
`participants`.`emergencyContactPhone` AS `emergencyContactPhone`,
`participants`.`eps` AS `eps`,
`participants`.`birthday` AS `birthday`,
`participants`.`memberOfGroupId` AS `memberOfGroupId`,
`participants`.`memberOfGroupName` AS `memberOfGroupName`,
`participants`.`lastRegistrationDate` AS `lastRegistrationDate`,
`participants`.`isVolunteer` AS `isVolunteer`,
`agreements_signatures`.`signatureRequest` AS `signatureRequest`,
`agreements_signatures`.`signature` AS `signature`,
`agreements_signatures`.`manualSignature` AS `manualSignature`,
`agreements_signatures`.`fromWhereWasSigned` AS `fromWhereWasSigned`,
`agreements_signatures`.`responsibleName` AS `responsibleName`,
`agreements_signatures`.`responsibleIdentificationNumber` AS `responsibleIdentificationNumber`,
`agreements_signatures`.`expeditionPlace` AS `expeditionPlace`,
`agreements_signatures`.`signedIn` AS `signedIn`
FROM
((`participants`
LEFT JOIN `participants_registrations` ON ((`participants_registrations`.`participantId` = `participants`.`id`)))
LEFT JOIN `agreements_signatures` ON ((`agreements_signatures`.`id` = `participants_registrations`.`agreementSignatureId`)))
Thanks any help.
RIGHT RESULTS IMAGE:
WRONG RESULTS IMAGE (VIEW):
Its because ORDER BY does not work with views, see this link, Its a limitation of SQL SERVER in views. It would be better to write this query without using a view
I have four tables, user, user_billingprofile, user_shippingprofile, and user_address.
user: userId, dateCreated
user_billingprofile: userId, address
user_shippingprofile: userId, address
user_address: random address crap
Here is the query I have to get a users billing and shipping profiles in one shot.
SELECT * FROM `user`
JOIN `user_billingprofile` ON `user`.`userId` = `user_billingprofile`.`userId`
JOIN `user_address` ON `user_billingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_shippingprofile` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_address` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
I get the error: #1066 - Not unique table/alias: 'user_address'.
Is there a way to take a simple join where a table is accessed twice in the same query, and separate the two results? Preferably with some kind of table prefix...
I'm a bit lost here. I know I could do this in two sepparate queries quite easily, but i'd like to learn how to do stuff like this in one shot.
Any help/suggestions/direction is greatly appreciated, thank you!.
Can you post the structure of your tables? Based on your query I'd say you need to consider changing it up a bit.
That said you can fix your current query by adding a table alias like so:
SELECT * FROM `user`
JOIN `user_billingprofile` ON `user`.`userId` = `user_billingprofile`.`userId`
JOIN `user_address` AS user_billing_address ON `user_billingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_shippingprofile` ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
JOIN `user_address` AS user_shipping_address ON `user_shippingprofile`.`currentAddress` = `user_address`.`addressId`
Note the AS clause I added. You'll probably need to alias the columns too (instead of SELECT * you likely will need SELECT user_shipping_address.address AS user_shipping_address_value, user_billing_address.address AS user_billing_address_value ... )
Hope that helps!