Get non zero ids count without where clause - mysql

I wont to get non zero funnel_id count. i get funnel_id count but is also show count of funnel_id is zero and here we do not add where clause here i also get page_count in this query.
SELECT `smart_projects`.project_id, `smart_projects`.business_id, `smart_projects`.title,
`page_pages`.`funnel_id` as `funnel_id`, count(distinct(page_pages.page_id) )as page_count, count(distinct(page_pages.funnel_id) )as funnel_count
FROM `smart_projects`
LEFT JOIN `page_pages` ON `smart_projects`.`project_id` = `page_pages`.`project_id`
WHERE smart_projects.status != 0
AND `smart_projects`.`business_id` = 'cd9412774edb11e9'
AND `smart_projects`.`created_date` BETWEEN 1558031400 AND 1558722600
GROUP BY `smart_projects`.`project_id`
ORDER BY `funnel_count` ASC
LIMIT 10
page_pages table is :
smart_projects table is :
result is :-
Expected Result is :

SELECT `smart_projects`.project_id, `smart_projects`.business_id, `smart_projects`.title,
`page_pages`.`funnel_id` as `funnel_id`, count(distinct(page_pages.page_id) )as page_count, count(distinct (CASE WHEN page_pages.funnel_id != 0 then page_pages.funnel_id ELSE NULL END ) ) as funnel_count
FROM `smart_projects`
LEFT JOIN `page_pages` ON `smart_projects`.`project_id` = `page_pages`.`project_id`
WHERE smart_projects.status != 0
AND `smart_projects`.`business_id` = 'cd9412774edb11e9'
GROUP BY `smart_projects`.`project_id`
ORDER BY `title` DESC

If you want to filter out zero values, using a having clause:
SELECT sp.project_id, sp.business_id, sp.title,
count(distinct pp.page_id ) as page_count,
count(distinct pp.funnel_id ) as funnel_count
FROM `smart_projects` sp LEFT JOIN
`page_pages` pp
ON sp.`project_id` = pp.`project_id`
WHERE sp.status <> 0 AND
sp.`business_id` = 'cd9412774edb11e9' AND
sp.`created_date` BETWEEN 1558031400 AND 1558722600
GROUP BY sp.`project_id`
HAVING funnel_count > 0
ORDER BY `funnel_count` ASC
LIMIT 10;
Notes:
Table aliases make the query easier to write and to read.
DISTINCT is not a function, it is a keyword. The following expression does not need parentheses.
funnel_id is not appropriate in the SELECT, because it is the argument to an aggregation function.

Related

How to select main item row from table using CASE WHERE conditions?

I have an array of products and I need to select the main photo of each product. My photo table consists of columns: id, product_id, photoname, flag, order.
'flag' = 1 when is the main photo and 'order' is the ordering of photos. Sometimes the 'flag' and 'order'are 0 (not set), so I need to assume the main photo is its 'id' ASC.
In my MySQL code I have:
private function getProducts($idUser) {
$products = DB::connection('mysql2')->select("SELECT
a.*
, (CASE WHEN photos.flag = 0 THEN
(
SELECT photoname
FROM mpy_product_photos
WHERE flag = 1 AND product_id = a.id LIMIT 1
)
ELSE photos.photoname END
) AS photoname
FROM mpy_products AS `a`
LEFT JOIN mpy_product_photos AS `photos` ON (photos.product_id = a.id)
WHERE a.user_id = '$idUsuario'
GROUP BY a.id
ORDER BY a.date DESC");
return $products;
}
When 'flag' = 0 for all 'photoname' from the same 'product_id', the return is null.
I've tried adding the following, along with many things but always get a Syntax error.
, (CASE WHEN photos.flag = 0 THEN
(
SELECT photoname
FROM mpy_product_photos
WHERE flag = 1 AND product_id = a.id LIMIT 1
)
ELSE
(
SELECT photoname
FROM mpy_product_photos
WHERE product_id = a.id ORDER BY photos.id LIMIT 1 END
)
) AS photoname
So when I don't have 'flag' = 1, I need to select and order by 'order' ASC. If 'order' = 0 in all rows, I need to select by 'id' ASC.
I've also tried the following, and at least I get a 'photoname' randomly (I guess) selected instead of null when all 'flag' = 0.
, (CASE WHEN photos.flag = 0 THEN
(
SELECT photoname
FROM mpy_product_photos
WHERE product_id = a.id ORDER BY photos.flag DESC LIMIT 1
)
ELSE photos.photoname END
) AS photoname
How can I solve this?
UPDATE: You specifically ask for a solution with CASE WHEN. In the meantime, I provide alternatives.
For MySQL 5.5+
select
a.*,
(select
photoname
from my_product_photos
where product_id = a.id
order by flag desc, ord asc, id asc
limit 1) as photoname
from my_product a;
If you're using MySQL 8.0, you can achieve this with the RANK window function rather simply as well
SELECT
product.*,
photo.photoname
FROM my_product product
JOIN (
SELECT
*,
RANK() OVER(PARTITION BY product_id ORDER BY flag DESC, ord ASC, id ASC) AS r
FROM my_product_photos
) photo ON photo.product_id = product.id AND photo.r = 1;
The RANK Function, as it's name implies, ranks the rows according to the given "rules". In the query, the rules are: Rank those with the higher flag, the lower order and lower id of the same product_id. This is going to be as a column of alias r. Then, you can just INNER JOIN as usual. With r you can then filter out the ones "less likely to be what you want".
This is a DB Fiddle with sample data. This might not match what you have in your own DB, so adjust as necessary.

MySQL - if count in select subquery is null change to 0

I have following query:
select `jobs`.*,
(SELECT COUNT(user_jobs_application.id) as count FROM user_jobs_application
join job_shifts on job_shifts.id = user_jobs_application.job_shift_id
where job_shifts.jobs_id = jobs.id
and user_jobs_application.status = 1
group by user_jobs_application.users_id
) as entries
from `jobs` where `jobs`.`deleted_at` is null order by `id` desc limit 25 offset 0
The subquery in select will give null instead of 0. Can I change this so if the value is null it will show 0?
Removing the group by clause from the subquery should be sufficient. It is not needed anyway, since it groups on the column you are filtering on (and it it was needed, then I would mean the subquery may return more than one row, which would generate a runtime error).
select
j.*,
(
select count(*) as count
from user_jobs_application uja
join job_shifts js on js.id = uja.job_shift_id
where js.jobs_id = j.id and uja.status = 1
) as entries
from jobs j
where j.deleted_at is null
order by id desc limit 25 offset 0
Other changes to your query:
presumably, user_jobs_application(id) is not nullable; if so, count(*) is good enough, and is more efficient than count(user_jobs_application.id)
table aliases make the query easier to read and write

MYSQL Order By Sequence

I need help with mysql order by, i have this query
SELECT
videos_views.videos_views_id,
videos_views.videos_views_date,
SUM(IF(MONTH(videos_views.videos_views_date) = 2, videos_views.videos_views_total, 0)) AS total_view,
videos.videos_id,
videos.videos_title,
videos.videos_description,
videos.videos_author_list_id,
author_list.author_list_name,
author_list.author_list_id
FROM videos
LEFT OUTER JOIN author_list
ON videos.videos_author_list_id = author_list.author_list_id
LEFT OUTER JOIN videos_views
ON videos.videos_id = videos_views.videos_views_id
WHERE author_list.author_list_video_type = 1
AND videos.videos_id >= 51108
GROUP BY videos_views.videos_views_id,
videos.videos_id
ORDER BY CASE WHEN MONTH(videos_views.videos_views_date) = 2 THEN SUM(videos_views.videos_views_total) END DESC,
CASE WHEN MONTH(videos_views.videos_views_date) <> 2 THEN videos.videos_id END DESC
LIMIT 11
And it returns the following results
If i use the first order by using DESC or ASC returns the same result above.
And i use the second order by using ASC returns the result bellow:
And I need the query to return the values in the following order bellow
Please Help me
Your results suggest that you want:
order by total_views desc, videos_id desc
You can reference column aliases (safely) in the order by.

Group and order by a column but donot include that column in results

I've been trying to figure out how I can modify this query so that the result set does not include the numHits. I want the same results in the same order, just not have the numHits included.
SELECT
`newel_inventoryKeywordIdDictionaryId`.`inventoryId`
,COUNT(`newel_inventoryKeywordIdDictionaryId`.`inventoryId`) as numHits
FROM
`newel_inventoryKeywordIdDictionaryId`
, `newel_inventoryDictionary`
WHERE
`newel_inventoryKeywordIdDictionaryId`.`dicId` = `newel_inventoryDictionary`.`dicId`
AND (
`newel_inventoryDictionary`.`word` = 'alabaster' OR `newel_inventoryDictionary`.`word` = 'chess'
)
GROUP BY inventoryId
ORDER BY numHits DESC;
sample results:
inventoryId, numHits
6928, 2
6929, 2
6924, 2
6925, 2
13772, 2
6926, 2
18203, 1
6931, 1
13863, 1
18402, 1
Desired Results:
inventoryId
6928
6929
6924
6925
13772
6926
18203
6931
13863
18402
Move the column from SELECT clause to ORDER BY clause:
SELECT
`newel_inventoryKeywordIdDictionaryId`.`inventoryId`
FROM
`newel_inventoryKeywordIdDictionaryId`
, `newel_inventoryDictionary`
WHERE
`newel_inventoryKeywordIdDictionaryId`.`dicId` = `newel_inventoryDictionary`.`dicId`
AND (
`newel_inventoryDictionary`.`word` = 'alabaster' OR `newel_inventoryDictionary`.`word` = 'chess'
)
GROUP BY inventoryId
ORDER BY COUNT(`newel_inventoryKeywordIdDictionaryId`.`inventoryId`) DESC;
SELECT
`newel_inventoryKeywordIdDictionaryId`.`inventoryId`
FROM
`newel_inventoryKeywordIdDictionaryId`
, `newel_inventoryDictionary`
WHERE
`newel_inventoryKeywordIdDictionaryId`.`dicId` = `newel_inventoryDictionary`.`dicId`
AND (
`newel_inventoryDictionary`.`word` = 'alabaster' OR `newel_inventoryDictionary`.`word` = 'chess'
)
GROUP BY inventoryId
ORDER BY COUNT(`newel_inventoryKeywordIdDictionaryId`.`inventoryId`) DESC;
You just need to put the aggregation in the ORDER BY. However, you should also:
Use explicit join syntax. Never use commas in the from clause.
Use table aliases. They make queries easier to write and to read.
Use in instead of a bunch of or statements.
Here is an improved version of the query:
SELECT kdi.inventoryId
FROM newel_inventoryKeywordIdDictionaryId kdi JOIN
newel_inventoryDictionary id
ON kdi.dicId = id.dictId
WHERE id.word IN ('alabaster', 'chess')
GROUP BY kdi.inventoryId
ORDER BY COUNT(*) DESC;

Mysql ANY NOT EQUAL TO subquery not working

I'm having a small issue with a query using ANY.
Select *, count(*) as m
from mp_bigrams_raw
where date_parsed=051213
and art_source='f'
and bigram != ANY(select feed_source from mp_feed_sources)
group by bigram
order by m DESC
limit 50;
The query runs but it's not excluding the items found in the subquery.
The original query worked when there was only 1 row in the subquery. Once I added more I got an error about more than 1 row.
Select *, count(*) as m
from mp_bigrams_raw
where date_parsed=051213
and art_source='f'
and bigram != (select feed_source from mp_feed_sources)
group by bigram
order by m DESC
limit 50;
From there I added ANY and the query runs but seems to ignore the !=. I'm guessing I'm missing something here.
Thanks
Why don't you use NOT IN
Select *, count(*) as m
from mp_bigrams_raw
where date_parsed=051213
and art_source='f'
and bigram NOT IN(select feed_source from mp_feed_sources)
group by bigram
order by m DESC
limit 50;
Try using a left join with an is null:
Select r.*, count(*) as m
from mp_bigrams_raw r
left join mp_feed_sources f on f.feed_source = r.bigram
where r.date_parsed=051213
and r.art_source='f'
and f.feed_source is null
group by r.bigram
order by m DESC
limit 50;
The condition ANY returns true (as far as the doc says), whenever the condition is true for any of the entries of the subselect, so if one of those selected fields is != bigram the clause evaluates to true.
NOT IN is what you want, so bigram is not in the list of selected values.