MYSQL Limit results - mysql

I've almost done with my query, but there is still one last issue to resolve. My query looks like this:
//execute the SQL query and return records
$result = mysql_query("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, 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
");
echo "<br>";
echo ("<img src=chart.php>");
echo "<br>";
echo ("<img src=chart_prov.php>");
//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>';
}
This part:
AND (ps_order_history.id_order_state) = '4' OR (ps_order_history.id_order_state) = '13'
causes the result to be displayed if the state of orders is either 4 or 13. The problem is that in the backend I can put it in those states many times, so if I'm not careful when updating orders, it will add the results more than one time.
Is it a way to limit that funktion to just handle latest update (have date_add in same table) or limit by 1?

Try to use
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, 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 ps_order_history.id = (select ps_order_history.id from ps_order_history where ps_orders.id_order = ps_order_history.id_order and MONTH(ps_order_history.date_add) = MONTH(CURDATE()) AND (ps_order_history.id_order_state) = '4' OR (ps_order_history.id_order_state) = '13' order by ps_order_history.date_add desc limit 1)
GROUP BY ps_orders.id_customer
ORDER BY SUM(ps_order_detail.product_weight) DESC
Maybe it helps.

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.

PHP - How to group from multiple sql queries

I got
for($i = $start_date;$start_date <= $end_date;$i->modify('+1 day')) {
$i->format('Y-m-d').'<br />';
$dates = $i->format('Y-m-d');
echo $query = "
SELECT md.dish_id
, md.daydate
, d.id
, d.dish_name
, d.weight
, d.price
FROM dishes d
LEFT
JOIN menu_details md
ON d.id = md.dish_id
WHERE md.daydate = '$dates'
";
$result = mysql_query($query);
}
while($row = mysql_fetch_array($result)) {
echo 'Date: '.$row['daydate'].'Name: '.$row['dish_name'].'<br />';
}
how can i row 'dish_name' for every date on a new row.In the database there are more then 1 row with same date=
You should try to avoid running queries in loops...
Try:
$query = "SELECT md.dish_id, md.daydate, d.id, d.dish_name, d.weight, d.price
FROM dishes d
LEFT JOIN menu_details md ON (d.id = md.dish_id)
WHERE md.daydate BETWEEN '$start_date' AND '$end_date'
GROUP BY md.daydate ";
$result = mysql_query($query);
while($row = mysql_fetch_array($result)) {
echo 'Date: '.$row['daydate'].'Name: '.$row['dish_name'].'<br />';
}
What is the group by for? I think it may cause you to lose some of the results...

Combination of two SQL queries

I have two separate SQL queries that I would like to combine to a single one if possible.
Query #1 yields all entries from a table in random order
Query #2 will afterwards check whether or not the result can be used
How can I achieve this in a single step directly in SQL?
Code:
// start with a query for all of the photos, returned in random order
$query = "
SELECT DISTINCT m.mediaID
, m.description
, m.path
, m.alwayson
, m.usecollfolder
, m.mediatypeID
FROM $media_table m
WHERE m.mediatypeID = 'photos'
ORDER BY RAND();
";
$result = mysql_query($query) or die ("$text[cannotexecutequery]: $query");
while( $imgrow = mysql_fetch_assoc( $result ) ) {
// if the picture is alwayson or we are allowing living to be displayed,
// we don't need to bother
// with any further checking
if ($imgrow[alwayson] || $allow_living_db ) {
break;
// otherwise, let's check for living
} else {
// this query will return rows of personIDs on the photo that are living
$query = "
SELECT l.personID
FROM $medialinks_table l
JOIN $people_table p ON l.personID = p.personID
WHERE l.mediaID = $imgrow[mediaID]
AND p.living = 1
";
$presult = mysql_query($query) or die ("$text[cannotexecutequery]: $query");
$rows = mysql_num_rows( $presult );
mysql_free_result( $presult );
// if no rows are returned, there are no living on the photo, so let's display it
if ($rows == 0) {
break;
}
}
SELECT DISTINCT m.mediaID
, m.description
, m.path
, m.alwayson
, m.usecollfolder
, m.mediatypeID
, l.personID
FROM $media_table m
JOIN $medialinks_table l
ON l.mediaID = m.mediaID
JOIN $people_table p
ON l.personID = p.personID
WHERE m.mediatypeID = 'photos'
AND p.living = 1
ORDER
BY RAND();

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

wordpress query_posts to look at meta info

I am looking to run a query with query_posts that lets me look at meta_fields.
I have done this once before and achieved the result I wanted but now for some reason adding an extra field into the equation returns nothing.
The query below returns all attachments where the lottery_year is equal to $y, and obviously $y can be 2011 or earlier.
Now my next step I want to bring in another meta_field called photo_technique and give that one a value.
Question, how do I do that?
$querystr = "
SELECT $wpdb->posts.*
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE ($wpdb->postmeta.meta_key = 'lottery_year' AND $wpdb->postmeta.meta_value = $y)
AND $wpdb->posts.post_type = 'attachment'
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
If you whant to display posts that have either lottery_year = $y ( or ) photo_technique = $x, you could use :
$querystr = "
SELECT $wpdb->posts.*
FROM $wpdb->posts
LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE ($wpdb->postmeta.meta_key = 'lottery_year' AND $wpdb->postmeta.meta_value = $y) OR ($wpdb->postmeta.meta_key = 'photo_technique' AND $wpdb->postmeta.meta_value = $x)
AND $wpdb->posts.post_type = 'attachment'
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
Edit
If you whant to display results that have both lottery_year = $y ( AND ) photo_technique = $x, you could use the following query :
$querystr = "
SELECT
$wpdb->posts.*
FROM
$wpdb->posts
INNER JOIN $wpdb->postmeta ON
$wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->postmeta.meta_key IN ( 'lottery_year', 'photo_technique' )
AND $wpdb->postmeta.meta_value IN ( '$y', '$x' )
WHERE $wpdb->posts.post_type = 'attachment'
GROUP BY $wpdb->posts.ID
HAVING COUNT(1) = 2
ORDER BY $wpdb->postmeta.meta_value ASC
LIMIT 100
";
Edit
The last query ( the AND one ) will fail in some circumstances. For example you whant
lottery_year = $y AND photo_technique = $x, but it will allso return results that have the $x and $y switched like : lottery_year = $x AND photo_technique = $y, it realy depends when you can rely on it or not, like do you have a photo_technique that is called for example '2001' ( witch could pass as a lottery_year too ) . Please be carefull with it or ask this question on dba.stackexchange.com or wordpress.stackexchange.com .