So I'm trying to get some total numbers of different tables in the database.
This is the query that I'm using
$this->db->select('
c.*,
SUM(rm.discount_value) as totalDiscount,
SUM(a.status = 0) as totalVisits,
SUM(a.status != 0) as totalAnnulations,
SUM(r.treatment_price + r.arrangement_price + r.product_price) + c.start_rev as totalRevenue
')
->join('customers c','c.customer_id = a.customer_id','left')
->join('revenue r','r.customer_id = a.customer_id','left')
->join('remarks rm','rm.customer_id = a.customer_id','left')
->from('agenda a')
->where('a.user_id',$user_id)
->where('a.customer_id',$customer_id)
->group_by('a.customer_id');
This results in the following query.
SELECT `c`.*,
SUM(rm.discount_value) as totalDiscount,
SUM(a.status = 0) as totalVisits, SUM(a.status != 0) as totalAnnulations,
SUM(r.treatment_price + r.arrangement_price + r.product_price) + c.start_rev as totalRevenue
FROM (`agenda` a)
LEFT JOIN `customers` c ON `c`.`customer_id` = `a`.`customer_id`
LEFT JOIN `revenue` r ON `r`.`customer_id` = `a`.`customer_id`
LEFT JOIN `remarks` rm ON `rm`.`customer_id` = `a`.`customer_id` WHERE `a`.`user_id` = '9' AND `a`.`customer_id` = '4134'
GROUP BY `a`.`customer_id`
This query is returning 4810 visits, but there are only 74.
This returns too many results. Its like its not using that a.customer_id
Any help is welcome, thanks in advance.
You are using GROUP BY with a column that does not appear in the SELECT. See how to use GROUP BY.
Related
I have this query that is inside another one that calculates avg per month, but when this query doesn't return anything, then I have an empty table as a result, but I want it to be a 0 instead, I think this result is because of the group by
select
coalesce(count(distinct t.order_id),0) as ordenes,
'Erradas' as tipo,
EXTRACT(MONTH FROM o.order_creation_date) as mes
from (
select
orders.order_id,
pd.missing ,
pd.incomplete ,
pd.damaged,
pd.status_code ,
r.reason ,
r.reason_type,
(case
when ((pd.missing is null) and (pd.incomplete is null) and (pd.damaged is null))
then NULL
when ((r.reason_type not in ('F', 'W')) and
(((pd.missing + pd.incomplete) + pd.damaged) > 0)) then 1
when ((r.reason = 'F') and (pd.missing > 0)) then 1
when ((r.reason = 'W') and (pd.missing > 0)) then 0
else 0 end) AS refund_result
from module.orders
inner join module.pack p on orders.order_id = p.order_id
inner join module.pack_d pd on p.asn = pd.asn
left join module.reason r on r.reason = p.reason
INNER JOIN module.mv_reporte mc ON orders.customer_id = mc.rut
WHERE mc.level = 'VIP'
) t
inner join ecommerce.orders o on o.order_no = t.id
where refund_result = 1
and o.order_creation_date BETWEEN '2022/01/01' AND '2022/12/31'
group by month
order by month
As you can see, I tried to use coalesce, but it didn't work
First question on here, so I apologise if I have missed something previously asked, or don't format this well....
My company has a custom CRM + database that I am attempting to improve. We need to find a list of properties that will not have their yearly service renewed. Currently, we do this by first finding properties that will have their service renewed, which is done with the following query:
SELECT DISTINCT
j.`property_id`
FROM
`jobs` AS j
LEFT JOIN `property` AS p
ON j.`property_id` = p.`property_id`
LEFT JOIN `agency` AS a
ON p.`agency_id` = a.`agency_id`
INNER JOIN `property_services` AS ps
ON (
j.`property_id` = ps.`property_id`
AND j.`service` = ps.`alarm_job_type_id`
)
WHERE ps.`service` = 1
AND a.`country_id` = 1
AND (
j.`status` = 'Pending'
OR j.`date` IS NULL
OR j.`date` = '0000-00-00'
OR j.`job_type` = 'Once-off'
OR j.`job_type` = '240v Rebook'
OR (
j.`date` >= '2019-04-22'
AND j.`job_type` = 'Yearly Maintenance'
)
)
Then we find the details we want to display for the user, excluding other items in the process:
SELECT DISTINCT
j.`property_id`,
p.`address_1` AS p_address1,
p.`address_2` AS p_address2,
p.`address_3` AS p_address3,
p.`state` AS p_state,
p.`postcode` AS p_postcode,
a.`agency_id`,
a.`agency_name`
FROM
`jobs` AS j
LEFT JOIN `property` AS p
ON j.`property_id` = p.`property_id`
LEFT JOIN `agency` AS a
ON p.`agency_id` = a.`agency_id`
INNER JOIN `property_services` AS ps
ON (
j.`property_id` = ps.`property_id`
AND j.`service` = ps.`alarm_job_type_id`
)
WHERE p.`property_id` NOT IN (INSERT HERE THE IDS YOU GOT FROM THE FIRST QUERY)
AND ps.`service` = 1
AND p.`deleted` = 0
AND p.`agency_deleted` = 0
AND a.`status` = 'active'
AND a.`country_id` = 1
ORDER BY j.`property_id` DESC
LIMIT 0, 50
Ideally, I'd like to combine these queries, or somehow optimise them, as the page currently takes 2+ minutes to load, even with indexing.
Again, my apologies, I am not a database or query expert, pretty sure the degree only included one or two subjects on the matter!
For the record (in case someone would find it helpful), the combined version is:
SELECT DISTINCT
j.`property_id`,
p.`address_1` AS p_address1,
p.`address_2` AS p_address2,
p.`address_3` AS p_address3,
p.`state` AS p_state,
p.`postcode` AS p_postcode,
a.`agency_id`,
a.`agency_name`
FROM
`jobs` AS j
LEFT JOIN `property` AS p
ON j.`property_id` = p.`property_id`
LEFT JOIN `agency` AS a
ON p.`agency_id` = a.`agency_id`
INNER JOIN `property_services` AS ps
ON (
j.`property_id` = ps.`property_id`
AND j.`service` = ps.`alarm_job_type_id`
)
WHERE p.`property_id` NOT IN
(SELECT DISTINCT
j.`property_id`
FROM
`jobs` AS j
LEFT JOIN `property` AS p
ON j.`property_id` = p.`property_id`
LEFT JOIN `agency` AS a
ON p.`agency_id` = a.`agency_id`
INNER JOIN `property_services` AS ps
ON (
j.`property_id` = ps.`property_id`
AND j.`service` = ps.`alarm_job_type_id`
)
WHERE ps.`service` = 1
AND a.`country_id` = 1
AND (
j.`status` = 'Pending'
OR j.`date` IS NULL
OR j.`date` = '0000-00-00'
OR j.`job_type` = 'Once-off'
OR j.`job_type` = '240v Rebook'
OR (
j.`date` >= '2019-05-08'
AND j.`job_type` = 'Yearly Maintenance'
)
))
AND ps.`service` = 1
AND p.`deleted` = 0
AND p.`agency_deleted` = 0
AND a.`status` = 'active'
AND a.`country_id` = 1
AND (
j.`status` != 'Booked'
AND j.`status` != 'To Be Booked'
AND j.`status` != 'Send Letters'
AND j.`status` != 'On Hold'
AND j.`status` != 'On Hold - COVID'
AND j.`status` != 'Pre Completion'
AND j.`status` != 'Merged Certificates'
)
AND j.`date` > DATE_ADD(NOW(), INTERVAL - 350 DAY)
ORDER BY j.`property_id` DESC
Someone outside of StackOverflow helped combine, but it didn't help...
We ended up having to add a marker and search for that, because this query took 193 seconds to run on our database.
Also, I totally get the requirement to provide a minimum reproducible example, and its my fault for not doing that.
I am generating a Member Leaderboard based on some field values.. Using Below SQL i am getting those values...
SELECT ue1.user_id,
ue1.meta_value coins ,
ue3.meta_value user_rank ,
ue2.meta_value gems,
COUNT(ue4.user_id) quiz_count,
COUNT(ue5.user_id) video_watch_count,
ue1.meta_value + ue3.meta_value + ue2.meta_value total_points
FROM `wp_usermeta` as ue1
INNER JOIN `wp_usermeta` as ue2 ON ue2.user_id = ue1.user_id
AND ue1.meta_key = '_coin_points'
AND ue2.meta_key = '_gem_points'
INNER JOIN `wp_usermeta` as ue3 ON ue3.user_id = ue1.user_id
AND ue3.meta_key = '_user_rank'
INNER JOIN `wp_gamipress_user_earnings` as ue4 ON ue4.user_id = ue1.user_id
AND ue4.post_type = 'quiz-game-master'
INNER JOIN `wp_gamipress_user_earnings` as ue5 ON ue5.user_id = ue1.user_id
AND ue5.post_type = 'video-game-master'
WHERE ue1.meta_value > 0
AND ue2.meta_value > 0
GROUP BY ue1.user_id, ue1.meta_value, ue2.meta_value, ue3.meta_value, ue4.user_id, ue5.user_id
ORDER BY total_points DESC LIMIT 0, 50
What i am getting is... Not Expected Query Result
See? video_watch_count is copying quiz_count value.. I don't know why? Would appreciate if you could help me out here.
Check you join statement. For both quiz_count, video_watch_count, you select data from table wp_gamipress_user_earnings. For each entry if join condition satisfied it will return user_id from corresponding table.
Finally you group it using user_id which is common to both join results.That's why you get same count.
I'm kind of new with Knex.js query builder and I'm currently having trouble with one somehow simple MySQL select. Here it is :
SELECT orders.*, coalesce(x.unread, 0) AS unread_messages
FROM orders
LEFT JOIN
(SELECT id_order, COUNT(*) AS unread
FROM chats
WHERE read_by_user = 0
GROUP BY id_order) AS x
ON x.id_order = orders.id_order
WHERE id_customer = 42
ORDER BY date_submitted;
I'm a bit lost reading Knex's doc, but should I use .joinRaw for the join and knex.raw for the coalesce command ?
https://runkit.com/embed/1olni3l68kn4
knex('orders')
.select(
'orders.*',
knex.raw('coalesce(??, 0) as ??', ['x.unread', 'unread_messages'])
)
.leftJoin(
knex('charts')
.select('id_order', knex.raw('count(*) as ??', ['unread']))
.where('read_by_use', 0).groupBy('id_order').as('x'),
'x.id_order',
'orders.id_order'
)
.where('id_customer', 42)
.orderBy('date_submitted')
produces
select
`orders`.*, coalesce(`x`.`unread`, 0) as `unread_messages`
from `orders`
left join (
select `id_order`, count(*) as `unread`
from `charts`
where `read_by_use` = ?
group by `id_order`
) as `x`
on `x`.`id_order` = `orders`.`id_order`
where `id_customer` = ?
order by `date_submitted` asc
For those who land here: that's my working solution with the great help of #Mikael.
selectFromWhere = db('orders')
.select('orders.*', db.raw('IFNULL(??, 0) as ??', ['x.unread', 'unread_messages']))
.leftJoin(
db('chats')
.select('id_order', db.raw('count(*) as ??', ['unread']))
.where('read_by_user', 0)
.groupBy('id_order')
.as('x'),
'x.id_order',
'orders.id_order'
)
.where('id_customer', req.user.id_customer);
I have some trouble to count more than 2 counts in mysql statement.
My count(b.entry_id) as totalbooking wont work. What have i done wrong? Is the statement setup also correctly made?
This is how i tried:
"SELECT
t.restaurant_id as restaurant_id, ct.title as title,
count(DISTINCT t.cardid) as totalmembers,
count(t.restaurant_id) as totaltransactions,
count(b.entry_id) as totalbooking
from transactions as t
inner join exp_menucard_booking as b on (t.restaurant_id = b.entry_id)
inner join exp_channel_titles as ct on (t.restaurant_id = ct.entry_id)
inner JOIN exp_channel_data as cd on (ct.entry_id = cd.entry_id)
where t.cardid != 88888888 and ct.status = 'open'
group by t.restaurant_id
order by ct.title asc";
Use this pattern to count subsets of the total rowset:
sum( case when ColumnToBeTested = trueCondition then 1 else 0 end) as SubCount