Two queries merging - mysql

I need to merge two queries:
First query:
SELECT `p`.`name`, `posts`.*
FROM `polls` `p`, `posts`
WHERE `p`.`id` = `posts`.`guid`
AND `first` = {$id}
AND `text` LIKE ?
with... second query:
SELECT SUM(`deleted` = 0) AS 'posts'
FROM `posts`
WHERE `first`
NOT IN
(
SELECT `id`
FROM `posts`
WHERE `deleted` = 1
AND `first` = `id`
) AND `first` = {$fid}
Is there any chance to merge them?

You can use a UNION. You'll have to make them return the same columns though. The second query will have to return blank values for everything else.

I don't know what the query is trying to achieve, or what kind of results the queries produce. I think query 1 searches for posts like text, query 2 searches for deleted posts by ID. I've done a jig around, it should work if both queries generate the same amount of rows.
Changes:
1 You'd need to change the AS in the second query to a unique name (so here, posts_sum).
2 I've also removed the second ID join.
Check it out:
SELECT `p`.`name`, `posts`.*, SUM(`deleted` = 0) AS 'posts_sum'
FROM `polls` `p`, `posts`
WHERE `p`.`id` = `posts`.`guid`
AND `first` = {$id}
AND `text` LIKE ?
AND `first`
NOT IN
(
SELECT `id`
FROM `posts`
WHERE `deleted` = 1
AND `first` = `id`
)

Related

A column returns null value in SQL statement containing multiple SELECTs

I inherited a particular code from a previous developer. I intend to build the application all over again, but I have to add some functionalities before I proceed.
Firstly, It's a 62 column table that has to do with accounting, and I also have to fetch values from different tables with a single call to get the values that I need before insertion.
Lets say I need to make an insertion into table dailysales and i need to get values from table a,b,c and d at the same time.
I already have an sql statement for fetching this values, and it works fine except that a particular column keeps returning as NULL.
Here's my code:
SELECT `gds_pnr_ref`, `transaction_date`,
(SELECT `lastname` FROM `a` WHERE `id` = `staff` LIMIT 1) as `lastname`,
(SELECT `firstname` FROM `a` WHERE `id` = `staff` LIMIT 1) as `firstname`,
(SELECT `department_name` FROM `b` WHERE `id` = `staff_department` LIMIT 1) as `department`,
(SELECT `name` FROM `b` WHERE `memo_serial` = '$some_value' LIMIT 1) as `pax_name`,
(SELECT `customer_name` FROM `c` WHERE `id` = `customer_name` LIMIT 1) as `customer`,
travel_product,
(SELECT `vendor_name` FROM `c` WHERE `id` = `vendor` LIMIT 1) as `vendor`
FROM `d` WHERE `id` = '$some_value' LIMIT 1
The column (SELECT customer_name FROM c WHERE id = customer_name LIMIT 1) as customer always returns as NULL but when i run it independently it gives me the appropriate value.
I'm very much opened to a better solution for going about this.
You should always qualify column names in a query. Presumably, you intend something like this:
SELECT d.`gds_pnr_ref`, d.`transaction_date`,
(SELECT a.`lastname` FROM `a` WHERE a.`id` = d.`staff` LIMIT 1) as `lastname`,
(SELECT a.`firstname` FROM `a` WHERE a.`id` = d.`staff` LIMIT 1) as `firstname`,
(SELECT b.`department_name` FROM `b` WHERE b.`id` = d.`staff_department` LIMIT 1) as `department`,
(SELECT b.`name` FROM `b` WHERE b.`memo_serial` = ? LIMIT 1) as `pax_name`,
(SELECT c.`customer_name` FROM `c` WHERE c.`id` = d.`customer_name` LIMIT 1) as `customer`,
d.travel_product,
(SELECT c.`vendor_name` FROM `c` WHERE c.`id` = d.`vendor` LIMIT 1) as `vendor`
FROM `d`
WHERE d.`id` = ?
LIMIT 1;
I have to guess where the columns come from -- so this might not be 100% correct.
Notice that I also replaced the string variables with the ? placeholder. This is a reminder that you should be using parameters for such values.
Thanks guys, but this is the query i finally went with that returns all my needed values with non as null.
SELECT `a`.`currency`,
`a`.`vendor_name`,
CONCAT(`c`.`lastname`, ' ', `c`.`firstname`) AS `actioned_by`,
`e`.`department_name` AS `department`,
`f`.`customer_name` AS `customer`,
`g`.`currency_name` AS `fl_currency`,
`b`.`name`,
`b`.`nuc`,
`b`.`tax`,
`b`.`comm` AS `comm_percen`,
`b`.`comm_tax` AS `comm_tax_value`,
`b`.`actual_comm`,
`b`.`service_charge`,
`b`.`dip`,
SUM(`b`.`vendor`) AS payable,
`b`.`charge` AS receivable
FROM ((((((`d`
INNER JOIN `b` ON `d`.`id` = `b`.`memo_serial`)
INNER JOIN `a` ON `d`.`vendor` = `a`.`id`)
INNER JOIN `c` ON `d`.`staff` = `c`.`id`)
INNER JOIN `e` ON `d`.`staff_department` = `e`.`id`)
INNER JOIN `f` ON `d`.`customer_name` = `f`.`id`)
INNER JOIN `g` ON `a`.`currency` = `g`.`id`) WHERE `d`.`id` = '$some_value'
Using sub queries had some limitations, like when i needed to pull out multiple entries of the a particular foreign key in a particular table. It keeps returning the first row value only. So i ended up using INNER JOIN to pull from 6 different tables to get my results and it's way neater

MySQL: Combine a subselect and array into one IN statment

I'm not sure if this is possible but what I like to do is the following:
I have a list of id's stored in a table
I have a list of numbers I have already
I want 1 in statement that joins the 2 eg,
SELCET * from `table1` where `ID` IN ( (SELECT `id` from `table2` where `columnA` = 'yes') or (1,2,3,4))
but I am not sure how I can combine the two results in one statement.
The easiest way would probably be to have two separate in conditions:
SELCET *
FROM `table1`
WHERE `id` IN (SELECT `id` FROM `table2` WHERE `columnA` = 'yes') OR
`id` IN (1,2,3,4)

Get rank of contestants from points table with additional and nested conditions

We're trying to calculate the rank of contestants for a specific contest, using the following select query. The GROUP_CONCAT workaround is actually a solution that was offered here on SO for a similar question.
However, as we added more conditions the query got long, untidy and is not DRY, I think as we have to repeat the same conditions for the GROUP_CONCAT subquery.
How can it be optimized? Or would a solution like programmatically calculate ranks and check conditions then populate the database, be the best solution in this case?
SELECT *,
-- Get the rank of contestants
FIND_IN_SET(`id`, (
SELECT GROUP_CONCAT(`id` ORDER BY `points` DESC, `created`)
FROM `contestants` `c2`
-- The following query is exactly the same as the on in the main query bellow.
WHERE `contest_id`=:contest_id
AND EXISTS (
SELECT `user_id`
FROM `item`
WHERE `user_id`=`c2`.`user_id`
AND `product_id` IN (
SELECT `id`
FROM `product`
WHERE `price`<=:max_price
AND `available`=:available
)
)
AND `state`=:state
-- ---------------------------------------------------------------------------
)
) AS `rank`
FROM `contestants`
-- ---------------------------------------------------------------------------
WHERE `contest_id`=:contest_id
AND EXISTS (
SELECT `user_id`
FROM `item`
WHERE `user_id`=`c2`.`user_id`
AND `product_id` IN (
SELECT `id`
FROM `product`
WHERE `price`<=:max_price
AND `available`=:available
)
)
AND `state`=:state
-- ---------------------------------------------------------------------------
ORDER BY `rank` ASC
LIMIT 10

Mysql single query to display the max points in table and points corresponding to a particular msisdn

I have a table which is having two columns msisdn,points.I require to display the max points in table and points corresponding to a particular msisdn through a single query.The query that i am using is based on sub queries and i don't think so that it is the most efficient way to do this.Guys kindly share an alternative optimized single query for this.
Table Structure:
CREATE TABLE `tbl_121314_point_base` (
`msisdn` bigint(12) NOT NULL DEFAULT '0',
`points` int(10) NOT NULL DEFAULT 0,
KEY `msisdn` (`msisdn`)
) ENGINE=INnoDB;
Current Query:
select (
select max(points) from tbl_121314_point_base ) as max_points,
(select points from tbl_121314_point_base where msisdn = 9024317476) as ori_points
from tbl_121314_point_base limit 1;
Another way you can rewrite your query using cross join use EXPLAIN plan to see performance of both queries
select p.points ori_points ,
t.max_points
from tbl_121314_point_base p
where p.msisdn = 9024317476
cross join(select max(points) max_points
from tbl_121314_point_base ) t
limit 1;

How to select top 5 usernames with highest score

I have two tables, username and score. Both are connected using user_id.
I want to select the top 5 usernames who have the highest score. I am trying following query but it is not working:
SELECT `user_name`
FROM `username`
WHERE `user_id` = ( SELECT `u_id`
FROM `score`
ORDER BY `high_score` DESC
LIMIT 5 )
I get this error when I run the above query: #1242 - Subquery returns more than 1 row
In your WHERE clause your are trying to assert the congruence or equality of one value (on the left side) to a list of values (on the right side).
Use the IN operator to achieve this because it will compare the left value with any of the right values.
The following is your corrected code.
SELECT `user_name`
FROM `username`
WHERE `user_id` IN(
SELECT `u_id`
FROM `score`
ORDER BY `high_score` DESC
LIMIT 5
);
As a manner of style using a join is clearer and more elegant especially for a simple query like this.
SELECT `u`.`user_name`
FROM `username` AS `u`
INNER JOIN `score` AS `s`
ON `u`.`user_id` = `s`.`u_id`
ORDER BY `s`.`high_score` DESC
LIMIT 5;
Try this:
SELECT `user_name`
FROM `username`,`score`
WHERE `user_id` = `u_id`
ORDER BY `high_score` DESC
LIMIT 5