How use custom alias field from select fields in join? - mysql

How use custom alias field from select fields in join?
SELECT LOWER(CONCAT(`ufn`.`value`, '.', `uln`.`value`, CAST(RAND()*1e6 AS UNSIGNED))) AS `newlogin`
FROM `user_firstname` AS `ufn`
INNER JOIN `user_lastname` AS `uln`
LEFT JOIN `user` AS `u` ON `u`.`login` = `newlogin`
WHERE `ufn`.`sex` = 'male' AND `u`.`id` IS NULL
ORDER BY RAND()
LIMIT 1
Result: sql-error.png
EDIT:
My solution, but, ...:
SELECT #newlogin
FROM (
SELECT #newlogin := LOWER(CONCAT(`ufn`.`value`, '.', `uln`.`value`, CAST(RAND()*1e6 AS UNSIGNED)))
FROM `user_firstname` AS `ufn`
INNER JOIN `user_lastname` AS `uln`
WHERE `ufn`.`sex` = 'male'
ORDER BY RAND()
LIMIT 1
) AS `ufnX`
LEFT JOIN `user` AS `u` ON `u`.`login` = #newlogin
WHERE `u`.`id` IS NULL

Create the new login in a subquery and join it in:
SELECT LOWER(CONCAT(`ufn`.`value`, '.', `uln`.`value`, nl.num)) AS newlogin
FROM (SELECT CAST(RAND()*1e6 AS UNSIGNED))) AS num
) nl CROSS JOIN
`user_firstname` ufn CROSS JOIN
`user_lastname` uln LEFT JOIN
`user` u
ON `u`.`login` = LOWER(CONCAT(ufn.`value`, '.', uln.`value`, nl.num))
WHERE `ufn`.`sex` = 'male' AND `u`.`id` IS NULL
ORDER BY RAND()
LIMIT 1;
Note I replaced the INNER JOIN with CROSS JOIN. INNER JOIN with no ON makes no sense.
EDIT:
You seem to want to test multiple values to get a match. You could try putting the comparison in the HAVING clause. That clause can reference columns in the SELECT:
SELECT LOWER(CONCAT(ufn.`value`, '.', uln.`value`, CAST(RAND()*1e6 AS UNSIGNED))) AS newlogin
FROM user_firstname` ufn CROSS JOIN
`user_lastname` uln
WHERE `ufn`.`sex` = 'male'
HAVING NOT EXISTS (SELECT 1
FROM user u
WHERE u.login = newlogin
)
ORDER BY RAND()
LIMIT 1;

Related

UPDATE - SELECT - MYSQL #1093 - You can't specify target table 'temp1' for update in FROM clause

I can't find solution to correct this big query, I always receive an error from database.
I have tre tables and I need to make changes on some attribute on some condition:
UPDATE o36t_orders as temp1,
mytable as temp2
SET
temp1.bonifico = 1,
temp2.ultimo = 1
WHERE
temp1.id_order IN (
SELECT
id_order
FROM o36t_orders
LEFT JOIN o36t_address ON (o36t_address.id_address = o36t_orders.id_address_delivery)
LEFT JOIN mytable ON (
mytable.Causale = CONCAT(
o36t_address.lastname,
' ',
o36t_address.firstname
)
)
WHERE
o36t_orders.bonifico <> 1
)
AND temp2.id IN (
SELECT
id
FROM o36t_orders
LEFT JOIN o36t_address ON (o36t_address.id_address = o36t_orders.id_address_delivery)
LEFT JOIN mytable ON (
mytable.Causale = CONCAT(
o36t_address.lastname,
' ',
o36t_address.firstname
)
)
WHERE
o36t_orders.bonifico <> 1
)
Since the subqueries of the 2 IN clauses are identical (except the retuned column), I think that you can do what you want by a straight inner join of the 2 tables and that subquery (returning both columns):
UPDATE o36t_orders temp1
INNER JOIN (
SELECT
id, id_order
FROM o36t_orders
LEFT JOIN o36t_address ON (o36t_address.id_address = o36t_orders.id_address_delivery)
LEFT JOIN mytable ON (
mytable.Causale = CONCAT(
o36t_address.lastname,
' ',
o36t_address.firstname
)
)
WHERE
o36t_orders.bonifico <> 1
) t ON t.id_order = temp1.id_order
INNER JOIN mytable temp2 ON temp2.id = t.id
SET
temp1.bonifico = 1,
temp2.ultimo = 1

MySQL Getting row numbers of table inside subquery

I have one query where I need to have number of rows of an table by particular ID:
SELECT
(CAST(`ot`.`value` AS DECIMAL(6,2))) AS `value`,
`op`.`orders_id`,
(
SELECT
COUNT(1) AS `total`
FROM
(
SELECT
`op2`.`concert_date`
FROM
`orders_products` `op2`
WHERE
`op2`.`orders_id` = `op`.`orders_id`
AND
`op2`.`concert_date` <> ''
GROUP BY CONCAT(`op2`.`concert_date`,' ',`op2`.`concert_time`)
) AS `e`
) AS `devider`
FROM
`categories` `c`
JOIN `products` `p` ON `p`.`section_id` = `c`.`section_id`
JOIN `orders_products` `op` ON `op`.`products_id` = `p`.`products_id`
JOIN `orders_total` `ot` ON `ot`.`orders_id` = `op`.`orders_id`
WHERE
`c`.`section_id` = 25
AND
`p`.`product_type` IN ('P')
AND
`ot`.`class` IN ('ot_shipping')
GROUP BY `op`.`orders_id`
The main problem is that I getting error
#1054 - Unknown column 'op.orders_id' in 'where clause'
And can't run this. I have separated query in my loop but that made performance issue and want to push it in one query. Any idea?
try removing sub-sub query and use COUNT(DISTINCT ..)
SELECT
(CAST(`ot`.`value` AS DECIMAL(6,2))) AS `value`,
`op`.`orders_id`,
(
SELECT
COUNT(DISTINCT CONCAT(`op2`.`concert_date`,' ',`op2`.`concert_time`))
FROM
`orders_products` `op2`
WHERE
`op2`.`orders_id` = `op`.`orders_id`
AND
`op2`.`concert_date` <> ''
) AS `devider`
FROM
`categories` `c`
JOIN `products` `p` ON `p`.`section_id` = `c`.`section_id`
JOIN `orders_products` `op` ON `op`.`products_id` = `p`.`products_id`
JOIN `orders_total` `ot` ON `ot`.`orders_id` = `op`.`orders_id`
WHERE
`c`.`section_id` = 25
AND
`p`.`product_type` IN ('P')
AND
`ot`.`class` IN ('ot_shipping')
GROUP BY `op`.`orders_id`
and you don't even need subquery or concat as long concert_date or concert_time is null
SELECT
(CAST(`ot`.`value` AS DECIMAL(6,2))) AS `value`,
`op`.`orders_id`,
COUNT(DISTINCT `op`.`concert_date`, `op`.`concert_time`) AS `devider`
FROM
`categories` `c`
JOIN `products` `p` ON `p`.`section_id` = `c`.`section_id`
LEFT JOIN `orders_products` `op` ON `op`.`products_id` = `p`.`products_id`
JOIN `orders_total` `ot` ON `ot`.`orders_id` = `op`.`orders_id`
WHERE
`c`.`section_id` = 25
AND
`p`.`product_type` IN ('P')
AND
`ot`.`class` IN ('ot_shipping')
GROUP BY `op`.`orders_id`
In this subquery:
SELECT
`op2`.`concert_date`
FROM
`orders_products` `op2`
WHERE
`op2`.`orders_id` = `op`.`orders_id`
AND
`op2`.`concert_date` <> ''
GROUP BY CONCAT(`op2`.`concert_date`,' ',`op2`.`concert_time`)
you are not selecting op as table.
Should be:
SELECT
`op2`.`concert_date`
FROM
`orders_products` `op2`, `orders_products` `op`
WHERE
`op2`.`orders_id` = `op`.`orders_id`
AND
`op2`.`concert_date` <> ''
GROUP BY CONCAT(`op2`.`concert_date`,' ',`op2`.`concert_time`)
Beside this you are making an implicit join while you should use explicit even here and the subquery should become:
SELECT
`op2`.`concert_date`
FROM
`orders_products` `op2` JOIN `orders_products` `op`
ON
`op2`.`orders_id` = `op`.`orders_id`
WHERE
`op2`.`concert_date` <> ''
GROUP BY CONCAT(`op2`.`concert_date`,' ',`op2`.`concert_time`)

MySQL Joined SELECT COUNT()

I wish to select results across several tables, but I only want to return rows based on the COUNT() result of joined SELECT query.
Here's how the query looks at the moment:
SELECT `s`.`venue_id` AS `id`,
CONCAT(`u`.`First_name`, ' ', `u`.`Surname`) AS `user_name`,
`u`.`avatar` AS `avatar`,
`u`.`facebookId` AS `fid`,
`x`.`imgs` AS `num_imgs`
FROM `new_shortlists_venues` `s`
INNER JOIN `new_shortlists` ON `new_shortlists`.`id` = `s`.`list_id`
INNER JOIN `users` `u` ON `u`.`id` = `new_shortlists`.`bride_id`
LEFT JOIN (SELECT `listing_id`, COUNT(*) `imgs` FROM `listingsImages`) `x` ON `s`.`venue_id` = `x`.`listing_id`
WHERE `new_shortlists`.`venues` > 4
AND `new_shortlists`.`bride_id` != 0
GROUP BY `s`.`list_id`
ORDER BY `s`.`date_added` DESC
LIMIT 6
For some reason, the query returns NULL for num_imgs. Essentially, I'd like to select only records which have at least 4 records in the listingsImages table.
Please note that this is for a legacy system, and I didn't design the DB! As a result, I have now option to change the schema.
You left off the GROUP BY of your subquery. Your current query is returning COUNT(*) associated with a random listing_id. Add GROUP BY listing_id and you should return the correct counts.
SELECT `s`.`venue_id` AS `id`,
CONCAT(`u`.`First_name`, ' ', `u`.`Surname`) AS `user_name`,
`u`.`avatar` AS `avatar`,
`u`.`facebookId` AS `fid`,
`x`.`imgs` AS `num_imgs`
FROM `new_shortlists_venues` `s`
INNER JOIN `new_shortlists` ON `new_shortlists`.`id` = `s`.`list_id`
INNER JOIN `users` `u` ON `u`.`id` = `new_shortlists`.`bride_id`
LEFT JOIN (SELECT `listing_id`, COUNT(*) `imgs`
FROM `listingsImages`
GROUP BY `listing_id`) `x` ON `s`.`venue_id` = `x`.`listing_id`
WHERE `new_shortlists`.`venues` > 4
AND `new_shortlists`.`bride_id` != 0
GROUP BY `s`.`list_id`
ORDER BY `s`.`date_added` DESC
LIMIT 6
And to return those with at least 4 records, just add that constraint to your WHERE criteria:
AND `x`.`imgs` >= 4
This might be the culprit:
ON `s`.`venue_id` = `x`.`listing_id`

Counting rows from a big mysql query (zend)

I a developing in zend and have a rather large mysql query. The query works fine and i get the list I expect. I am doing this using Select->Where.... below is the query.
SELECT DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
Only problem is when I try to count the rows in a mysql query I only get 1 returned. below is the query
SELECT DISTINCT count(*) AS `rowCount` FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
i generate this from by using the same 'select' that generated the first query but I reset the columns and add count in.
$this->getAdapter()->setFetchMode(Zend_Db::FETCH_ASSOC);
$select
->reset( Zend_Db_Select::COLUMNS)
->columns(array('count('.$column.') as rowCount'));
$rowCount = $this->getAdapter()->fetchOne($select);
This method works fine for all my other queries only this one i am having trouble with. I suspect it has something to do the 'CASE' I have in there but it is strange because I am getting the correct rows the the first query. Any ideas. Thanks.
FYI below are two queries that I have working successfully.
SELECT DISTINCT `po`.* FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
SELECT DISTINCT count(*) AS `rowCount` FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
In this one I have 4 rows returned in the first query and 'int 4' returned for the second one. Does anyone know why it doesnt work for the big query?
Move your DISTINCT.
SELECT COUNT(DISTINCT `po`.*) AS `rowCount` ...
Ok figured it out It was the GROUP BY that was causing only 1 result to be returned. Thanks Interrobang for you help I am sure that using DISTINCT incorrectly will have caused me a headache in the future.
Try using SQL_CALC_FOUND_ROWS in your query?
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
Using SQL_CALC_FOUND_ROWS is mysql-specific, but it's pretty nice for getting a full record count even when your initial query contains a limit. Once you get the count, don't include SQL_CALC_FOUND_ROWS in subsequent queries for extra records since that will cause extra load on your query.
Your initial query would be:
SELECT SQL_CALC_FOUND_ROWS DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` ...
You'll have to do a subsequent call after your initial query executes to get the count by doing a SELECT FOUND_ROWS().
If you do a little searching, you'll find someone who extended Zend_Db_Select to include this ability.

MySQL - LEFT JOIN and NOT IN

I try to avoid subqueries due to the fact they usually have much lower performance than a proper join.
This is my current NOT working query:
SELECT
a.`email_list_id`, a.`category_id`, a.`name`
FROM
`email_lists`AS a
LEFT JOIN `email_autoresponders` AS b
ON ( a.`website_id` = b.`website_id` )
WHERE
a.`website_id` = [...]
AND a.`category_id` <> 0
AND a.`email_list_id` <> b.`email_list_id`
GROUP BY
a.`email_list_id`
ORDER BY a.`name`
This query works:
SELECT
`email_list_id`, `category_id`, `name`
FROM
`email_lists`
WHERE
`website_id` = [...]
AND `category_id` <> 0
AND `email_list_id` NOT IN (
SELECT
`email_list_id`
FROM
`email_autoresponders`
WHERE `website_id` = [...]
)
GROUP BY
`email_list_id`
ORDER BY
`name`
Is there any way to do this with a left join? I've tried a number of different options.
After rethinking it a bit, this might work i believe:
SELECT
a.`email_list_id`, a.`category_id`, a.`name`
FROM
`email_lists`AS a
LEFT JOIN `email_autoresponders` AS b
ON ( a.`website_id` = b.`website_id` and a.`email_list_id` = b.`email_list_id` )
WHERE
a.`website_id` = [...]
AND a.`category_id` <> 0
AND b.`email_list_id` is NULL
GROUP BY
a.`email_list_id`
ORDER BY a.`name`
For starters, add the inequality check on email_list_id to the join criteria, instead of having it in your WHERE clause:
LEFT JOIN `email_autoresponders` AS b
ON ( a.`website_id` = b.`website_id`
AND a.`email_list_id` <> b.`email_list_id` )
Though I'm not sure the scenario you mention calls for vast optimizations, this is a way to use a join rather than a subquery...