I have the following straightforward query which is part of a garbage collection script. The script is supposed to delete unused shopping carts. A cart is unused when it was updated more than 24 hours ago and is not attached to an order or a user.
$query = "SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`, COUNT(comm_orders.cart_id) AS `c1`, COUNT(comm_users.cart_id) AS `c2` " .
"FROM `comm_cart` " .
"LEFT JOIN `comm_orders` ON comm_cart.id=comm_orders.cart_id " .
"LEFT JOIN `comm_users` ON comm_cart.id=comm_users.cart_id " .
"GROUP BY comm_cart.id ";
"HAVING `diff`>86400 AND `c1`=0 AND `c2`=0";
The query finds too many carts: it also tags the ones that have a c1>0 or c2>0 and I can't figure out why. Any clues?
I suspect that you are joining along two different dimensions. The easy fix is to use distinct:
SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`,
COUNT(DISTINCT comm_orders.cart_id) AS `c1`, COUNT(DISTINCT comm_users.cart_id) AS `c2` " .
The better solution would be to use not exists for these two conditions:
FROM comm_carts cc
WHERE not exists (select 1 from comm_orders co where cc.id = co.cart_id )
not exists (select 1 from comm_users cu where cc.id = cu.cart_id )
You don't even need the group by, an isnull condition in the where would work wonders, of course I suggest using Gordon's suggestion of the not exists, but if you want the minimum change this would be is.
SELECT
comm_cart.id AS `cart_id`,
(UNIX_TIMESTAMP() - comm_cart.update_date) AS `diff`
FROM `comm_cart`
LEFT JOIN `comm_orders`
ON comm_cart.id=comm_orders.cart_id
LEFT JOIN `comm_users`
ON comm_cart.id=comm_users.cart_id
WHERE
comm_orders.cart_id IS NULL
AND
comm_users.cart_id IS NULL
Oh, and I've used UNIX_TIMESTAMP() instead of the PHP time function, same effect, but this avoids mixing PHP and SQL.
if you only want to get data with c1=0 and c2=0 then you need to write a where condition instead of having before group by,
$query = "SELECT comm_cart.id AS `cart_id`, (" . time() . " - comm_cart.update_date) AS `diff`, COUNT(comm_orders.cart_id) AS `c1`, COUNT(comm_users.cart_id) AS `c2` " .
"FROM `comm_cart` " .
"LEFT JOIN `comm_orders` ON comm_cart.id=comm_orders.cart_id " .
"LEFT JOIN `comm_users` ON comm_cart.id=comm_users.cart_id " .
" where c1=0 and c2 =0 and diff >86400 GROUP BY comm_cart.id;
Related
So I am trying to pull information about business listings from a wordpress database. The information is stored in the wp_posts table and the wp_postmeta table where all of the additional business information is listed.
The wp_postmeta table saves data like this: each piece of data has it's own row, the information is not stored as a serialized array all in one row.
Here is my database query so far:
$wpdb->get_results(
" SELECT * FROM " . $wpdb->posts .
" LEFT JOIN " . $wpdb->postmeta .
" ON " . $wpdb->posts . ".ID = " . $wpdb->postmeta . ".POST_ID" .
" WHERE " . $wpdb->posts . ".POST_TYPE = 'lv_listing' " .
" AND " . $wpdb->posts . ".POST_STATUS = 'publish' " .
" GROUP BY " . $wpdb->posts . ".ID");
Currently, each set of results gives me only one row from the wp_postmeta table, where I am expecting like 20 rows that should match the ID I am grouping by.
What am I doing wrong?
As per my understanding ,can you execute a query in the MySQL database and check if the Data is coming as per your req or not in the database .
Below is the syntax of the left outer join
SELECT column_name(s)
FROM table1
LEFT JOIN table2 ON table1.column_name = table2.column_name;
i am trying to write a query which will help me recover class, batch, and institution details from db
so far i have managed to make the following work:
SELECT
gallery.path_url AS insimage,
r3.*
FROM
gallery
INNER JOIN (
SELECT
institution.id AS insid,
institution.ProfileImageID,
institution.`name` AS insname,
institution.Locality AS inslocality,
institution.RegistrationFee AS ins_reg_fee,
institution.IsTrail AS ins_is_trail,
institution.LatLong AS latlong,
r2., activity.`name` AS activityname
FROM
institution
INNER JOIN (
SELECT
class., count() AS batch_count,
r1.
FROM
class
INNER JOIN (
SELECT
batch.ID AS batch_id,
batch.ClassID AS class_id,
batch.LevelID AS level_id,
batch.agegroupID AS agegroup_id,
count(*) AS num_batches,
min(Price) AS min_price,
max(Price) AS max_price
FROM
batch,
batchstarttimes
WHERE
batch.ID = batchstarttimes.BatchID
AND batchstarttimes.StartTime BETWEEN '" . $sttime . "'
AND '" . $endtime . "'
GROUP BY
batch.ID
) AS r1
WHERE
r1.class_id = class.ID
GROUP BY
r1.class_id
) AS r2 ON r2.institutionid = institution.id
INNER JOIN activity ON activity.id = r2.activityid
WHERE
activity.`name` LIKE '%" . $searchterm . "%'
AND institution.Locality LIKE '%" . $locality . "%'
AND institution.StatusID = 1
AND level_id = 1
AND agegroup_id = 5
) AS r3 ON r3.ProfileImageID = gallery.ID
I am stuck when i try to add two more filters batch.LevelID and batch.agegroupID
any way i can get help or someone point me to a sql visualizr tool will be helpful.
In your WHERE clause, replace:
AND level_id = 1
AND agegroup_id = 5
with:
AND batch.LevelID = CASE WHEN " . $levelID . " = 0 THEN batch.LevelID ELSE " . $levelID . " END
AND batch.agegroupID = CASE WHEN " . $ageGroupID . " = 0 THEN batch.agegroupID ELSE " . $ageGroupID . " END
The point is to compare batch.LevelID and batch.agegroupID against themselves if you want to ignore them for the filtering (this way they'll always be true) or compare them against $levelID and $ageGroupID values for specific rows.
Also, it's not recommended to use the variables directly in the query, as it's vulnerable to SQL injections attacks. Read about prepared statements here.
I have a query and i want random result on advertisement table. Advertise table have own id but when i use RAND(advertise.id) it won't work and i don't know how it will. I am using laravel framework so if possible i can use PHP also to show random advertise result. Here is code can anyone tell me where i use RAND() Mysql function.
SELECT providers.id,
adv__managements.id AS 'adv_id',
adv__managements.images,
adv__managements.categories,
adv__managements.subcategories,
adv__managements.title,
adv__managements.description,
adv__managements.role,
adv__managements.plan_id,
userinformation.user_id,
userinformation.zip_code,
plans.active
FROM userinformation INNER JOIN providers ON userinformation.user_id = providers.user_id
INNER JOIN adv__managements ON adv__managements.range = providers.range
INNER JOIN plans ON plans.user_id = userinformation.user_id
where GetDistance('km'," . doubleval($info->lat) . ", " . doubleval($info->lon) .", " . doubleval(\Auth::user()->userinfo->latitude) . ", " . doubleval(\Auth::user()->userinfo->longitude) . ") < providers.range AND plans.active = 1 LIMIT 3
And can anyone tell how to convert this query into laravel ?
I don't know how to fix this thing a little help would be good.
Error : table/alias is not unique.
Why do i got this error? I believe why joins are correct.Please help
$q = "SELECT * FROM `curriculum` "
. "INNER JOIN `subject` ON `curriculum`.`subject`=`subject`.`sub_id` "
. "LEFT JOIN `subject` ON `curriculum`.`cur_pr`=`subject`.`sub_id` "
. "WHERE `course`=:cid and `cur_year`=1";
Change your Code to
$q = "SELECT * FROM `curriculum` AS A "
. "INNER JOIN `subject` AS B ON `A`.`subject`=`B`.`sub_id` "
. "LEFT JOIN `subject` AS C ON `A`.`cur_pr`=`C`.`sub_id` "
. "WHERE `course`=:cid and `cur_year`=1";
If you want to join Same tables again use Table Aliases Here AS is used to this purpose
You get an error that says table/alias is not unique because this line code:
. "LEFT JOIN subject ON curriculum.cur_pr=subject.sub_id "
It don't know what subject is belong to what table ( first one or the second one). You can try this code above
$q = "SELECT * FROM `curriculum` AS cu "
. "INNER JOIN `subject` AS su1 ON `cu`.`subject`=`su1`.`sub_id` "
. "LEFT JOIN `subject` AS su2 ON `cu`.`cur_pr`=`su2`.`sub_id` "
. "WHERE `cu.course`=:cid and `cu.cur_year`=1";
I have this code:
select count(distinct affiliate_orders_id) as count
, sum(affiliate_value) as total
, sum(affiliate_payment) as payment
from " . TABLE_AFFILIATE_SALES . " a
left join " . TABLE_ORDERS . " o on (a.affiliate_orders_id = o.orders_id)
where a.affiliate_orders_id = o.orders_id
and o.orders_status >= " . AFFILIATE_PAYMENT_ORDER_MIN_STATUS . "
";
$affiliate_sales_query= tep_db_query($affiliate_sales_raw);
$affiliate_sales= tep_db_fetch_array($affiliate_sales_query);
So, $affiliate_sales['total'] = 128000 when in fact it should be 32000 becuase there are multiple affiliate_values and affiliate_orders_id. The affilaite_values some have the same values so these cannot be distinct. affilaite_orders_id have all unique values but there are multiple rows of this and needs to be distinct. Then the affiliate_values has to sum up based on the distinct rows of affiliate_orders_id to get an accurate sum.
I'm trying to get the sum of all affiliate_values bused on how many distinct affiliate_orders_id are in the table.
Based on your update I think this will get you what you're looking for. You need to use a subQuery
SELECT COUNT(a) COUNT, SUM(av) total, SUM(ap) aptotal
FROM (
SELECT affiliate_orders_id a, affiliate_value av, SUM(affiliate_payment) AS ap
from " . TABLE_AFFILIATE_SALES . " a
left join " . TABLE_ORDERS . " o on (a.affiliate_orders_id = o.orders_id
GROUP BY affiliate_orders_id, affiliate_value)
where a.affiliate_orders_id = o.orders_id
and o.orders_status >= " . AFFILIATE_PAYMENT_ORDER_MIN_STATUS . ") a
Now this leads to a bigger question. Are you missing a join condition in your tables? Typically you shouldn't have duplicate date returned in a query, so I would suggest double checking your query is joining properly first.