SELECT column/s based on boolean value - mysql

I have a left join select statement that I want to select specific columns based on the value of a variable that has either a '0' or a '1'. I thought I could implement this using CASE, but I don't seem to be having any luck.
If $variable contains a '0' I want my select statement to retrieve only users.user, table2.total1 and table2.total2, but if the $variable contains a '1' I want to select only users.user and table2.total.
$value = '1';
$conn->query(
"select users.user, table2.total, table2.total1, table2.total2
FROM users
LEFT JOIN table2 on users.user = table2.total AND $table2.date = CURDATE()
WHERE users.user = 'marketing' OR users.user = 'sales'
");
Does anyone have any ideas? Thanks.

You don't need to do this with sql, if in fact the query differ only by the select clause you could use a conditional and a variable:
$value = '1';
if($variable == '1') {
$select = "select users.user, table2.total1, table2.total2 ";
}
else {
$select = "select users.user, table2.total ";
}
$conn->query(
$select . "
FROM users
LEFT JOIN table2 on users.user = table2.total AND $table2.date = CURDATE()
WHERE users.user = 'marketing' OR users.user = 'sales'
");

Related

Query return empty result but data exist

I'm using Slim with PDO with MySql for return a specific list of matches available in my database. My query is this:
SELECT m.*,
t.name AS home_team_name,
t2.name AS away_team_name
FROM `match` m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team t2 ON m.away_team_id = t2.id
WHERE (home_team_id = 117 OR away_team_id = 117) AND round_id = 488
if I execute this query I'll get a list of matches:
but inside the API developed with Slim I get an empty array. This is the method structure:
$app->get('/match/get_matches_by_team/{round_id}/{team_id}/{type}', function (Request $request, Response $response, array $args)
{
$query = "SELECT m.*,
t.name AS home_team_name,
t2.name AS away_team_name
FROM `match` m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team t2 ON m.away_team_id = t2.id
WHERE ";
switch($args["type"])
{
case "home":
$query .= "home_team_id = :team_id AND ";
break;
case "away":
$query .= "away_team_id = :team_id AND ";
break;
default:
$query .= "(home_team_id = :team_id OR away_team_id = :team_id) AND ";
break;
}
$query .= "round_id = :round_id";
$sql = $this->db->prepare($query);
$sql->bindParam("team_id", $args["team_id"]);
$sql->bindParam("round_id", $args["round_id"]);
$sql->execute();
$result = $sql->fetchAll();
return $response->withJson($result);
});
what I did wrong?
Thanks in advance for any help.
UPDATE
If I do echo $query; return; I'll get:
SELECT m.*,
t.name AS home_team_name,
t2.name AS away_team_name
FROM `match` m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team t2 ON m.away_team_id = t2.id
WHERE away_team_id = :team_id AND round_id = :round_id
supposing to pass away, if instead I pass all I'll get:
SELECT m.*,
t.name AS home_team_name,
t2.name AS away_team_name
FROM `match` m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team t2 ON m.away_team_id = t2.id
WHERE (home_team_id = :team_id OR away_team_id = :team_id) AND round_id = :round_id
UPDATE 2
Method updated with proposed hints
$app->get('/match/get_matches_by_team
/{round_id}/{team_id}/{type}', function (Request $request, Response $response, array $args)
{
$query = "SELECT m.*,
t.name AS home_team_name,
t2.name AS away_team_name
FROM `match` m
LEFT JOIN team t ON m.home_team_id = t.id
LEFT JOIN team t2 ON m.away_team_id = t2.id
WHERE ";
switch($args["type"])
{
case "home":
$query .= "home_team_id = :home_team_id
AND ";
break;
case "away":
$query .= "away_team_id = :away_team_id AND ";
break;
default:
$query .= "(home_team_id = :home_team_id OR away_team_id = :away_team_id) AND ";
break;
}
$query .= "round_id = :round_id";
$sql = $this->db->prepare($query);
$sql->bindParam("home_team_id", $args["team_id"]);
$sql->bindParam("away_team_id", $args["team_id"]);
$sql->bindParam("round_id", $args["round_id"]);
$sql->execute();
$result = $sql->fetchAll();
return $response->withJson($result);
});
yours:
$sql->bindParam("team_id", $args["team_id"]);
$sql->bindParam("round_id", $args["round_id"]);
try this, the params might be needed to be formatted differently
$sql->bindParam(":team_id", $args["team_id"], PDO::PARAM_INT);
$sql->bindParam(":round_id", $args["round_id"], PDO::PARAM_INT);
or
$sql->bindParam(":team_id", $args["team_id"]);
$sql->bindParam(":round_id", $args["round_id"]);
When the default switch is selected, you are trying to bind a value with the same parameter marker (in your case :team_id) twice. In order for this to work you have to turn on emulation mode in PDO.
http://www.php.net/manual/en/pdo.prepare.php
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name more than once in a prepared statement, unless emulation mode is on.

Using 2 WHERE clauses

I am trying to do two WHERE clauses after each other and its not displaying what I want.
SELECT FROM users LEFT JOIN table2 on users.user = table2.total AND $table2.date = CURDATE() WHERE users.value = '$value' WHERE users.user = 'marketing' OR users.user = 'sales'";
I want to display all users that match what is stored in $value, along with this I also want all users that have a user value of 'marketing' OR 'sales'. Currently it is displaying all users, even ones that don't have the correct value in $variable. It looks like it is grouping my two WHERE clauses together but I want them to be separate. Any thoughts?
There were a few problems in your query I fixed. You can't use two where clauses. In this specific case, use in to select all rows where one field can be one of a specific list:
SELECT *
FROM users
LEFT
JOIN table2
on users.user = table2.total
AND table2.date = CURDATE()
WHERE users.value = '$value'
AND users.user in ( 'marketing', 'sales' )
You can add more conditions concatenating them by the 'AND' keyword. Like this:
SELECT *
FROM
users
LEFT JOIN table2 on
users.user = table2.total AND
table2.date = CURDATE()
WHERE
users.value = '$value' AND
(users.user = 'marketing' OR users.user = 'sales')
But I think this could be a bit easier to read and maybe meeting better your requirements:
SELECT *
FROM
users
LEFT JOIN table2 on
users.user = table2.total
WHERE
users.value = '$value' AND
users.user in ('marketing', 'sales') AND
table2.date = CURDATE()

query execution is too long to load

can i minimize or shorter (if ever) this query? this query takes too long to load, how can I shorten the execution of this query? thanks.
this is my sql query:
$sql = "
SELECT
i.ID
FROM item_tb i
WHERE
i.coID = '". $_SESSION['coID'] ."'
AND i.isProduct = '1'
AND i.isBom = '0'
AND NOT EXISTS(
SELECT
s.ID
FROM
stocks_tb s
WHERE
i.ID = s.itemID
AND s.brID = '". $brID ."'
)
";
I guess that your query converted LEFT JOIN as follows:
SELECT
i.ID
FROM item_tb i LEFT JOIN stocks_tb s ON i.ID = s.itemID
WHERE
i.coID = '". $_SESSION['coID'] ."'
AND i.isProduct = '1'
AND i.isBom = '0'
AND s.brID = '".$brId."'
AND s.itemID IS NULL;
and this is faster than your query.
You use many AND operator... Use bracket within the AND condition.. That's it

How to write a complex sql query in zend2

I want to write a mySQL query like the following in zend framework 2.
How to convert it in zend Db select convention?
SELECT profiles.*,
user.email,
user.first_name,
user.last_name,
portfilio_images.profileImage,
images.url AS imgurl
FROM profiles
INNER JOIN user ON user.user_id = profiles.ownerId
LEFT JOIN (
SELECT *
FROM portfilio_images
WHERE portfilio_images.profileImage = '1'
) as portfilio_images ON portfilio_images.profileId = profiles.id
LEFT JOIN images ON images.id = portfilio_images.imageId
WHERE profiles.ownerId != '4' AND (profiles.name LIKE '%a%' OR user.first_name LIKE '%a%' OR user.last_name LIKE '%a%')
GROUP BY user.user_id
You can also use Zend\Db\Sql\Select that allows you to build complex queries programatically. See the documentation here:
http://zf2.readthedocs.org/en/release-2.1.1/modules/zend.db.sql.html#zend-db-sql-select
You could always just perform a raw query:
$sql = "SELECT * FROM test";
$statement = $abAdapter->query($sql);
$result = $statement->execute();
$resultSet = new ResultSet;
$resultSet->initialize($result);
return $resultSet;
Or if you want to add some parameters
$sql = "SELECT * FROM test where col = ?";
$statement = $dbAdapter->query($sql);
$result = $statement->execute(array(99));
$resultSet = new ResultSet;
$resultSet->initialize($result);
return $resultSet;

MYSQL multiply if?

I have a query that looks like this:
//execute the SQL query and return records
$result = mysql_query("SELECT SUM(ps_order_detail.product_weight) as total_provision, COUNT(ps_order_detail.id_order_detail) as antal_ordrar, ps_customer.firstname
FROM ps_order_detail
JOIN ps_orders ON ps_order_detail.id_order = ps_orders.id_order
JOIN ps_order_history ON ps_orders.id_order = ps_order_history.id_order
JOIN ps_customer ON ps_orders.id_customer = ps_customer.id_customer
WHERE MONTH(ps_order_history.date_add) = MONTH(CURDATE()) AND (ps_order_history.id_order_state) = '4' OR (ps_order_history.id_order_state) = '13'
GROUP BY ps_orders.id_customer
ORDER BY SUM(ps_order_detail.product_weight) DESC
");
//fetch tha data from the database
while ($row = mysql_fetch_array($result))
{
echo '<font size="3">';
echo " Namn: ".$row{'firstname'}. "";
echo " Provision: ".$row{'total_provision'}. "";
echo " Abonnemang: ".$row{'antal_ordrar'}. "";
echo '<br>';
echo '</font size>';
}
It works fine but what i wana do is if the result "antal_ordrar" is larger than say 50 i wana multiply the result "total_provision" with 1,2 (add an extra 20% to the result)
Im new on mysql and are kinda stuck. Any ideas?
SELECT SUM(ps_order_detail.product_weight) *
IF( COUNT(ps_order_detail.id_order_detail) > 50, 1.2, 1 ) AS total_provision,
COUNT(ps_order_detail.id_order_detail) AS antal_ordrar, ...
First, wrap this in a subquery:
SELECT
-- use the if statement
IF( antal_ordrar > 50, total_provision * 1.2, total_provision ),
antal_ordrar,
firstname
FROM
-- create a subquery so you can reuse the data.
( SELECT SUM(ps_order_detail.product_weight) as total_provision,
COUNT(ps_order_detail.id_order_detail) as antal_ordrar,
ps_customer.firstname as firstname
FROM ps_order_detail
-- are you sure you need this many joins?
JOIN ps_orders ON ps_order_detail.id_order = ps_orders.id_order
JOIN ps_order_history ON ps_orders.id_order = ps_order_history.id_order
JOIN ps_customer ON ps_orders.id_customer = ps_customer.id_customer
-- group by normally uses the 'having' keyword.
WHERE MONTH(ps_order_history.date_add) = MONTH(CURDATE())
AND (ps_order_history.id_order_state) = '4'
OR (ps_order_history.id_order_state) = '13'
GROUP BY ps_orders.id_customer
ORDER BY SUM(ps_order_detail.product_weight) DESC )
-- an alias for your subquery so you can treat it like a table.
tbl;
Just noticed this. You're using braces when you mean brackets: $row{'total_provision'} should be $row['total_provision'].
Try to add to select
if (antal_ordrar > 50, total_provision * 1.2, total_provision) as total_provision