Selecting value corresponding with MAX value of a group - mysql

I am trying to get the OXSEOURL of my OXSEO table.
Structure:
oxobjectid | oxseourl | oxparams
Data:
http://imageshack.com/a/img268/7443/3xr4.png
http://imageshack.com/a/img42/315/8bdu.png
My deepest SEO URL always has the higher value in OXPARAMS field.
Only the numeric values, the others are never count..
Return should be:
http://imageshack.com/a/img29/8404/4jbv.png
I found a solution yesterday, but it was very slow, now I am trying to get a faster way to do it.
So I would like to get the oxseourl for the same oxobjectid with the max oxparams value.
I have more than 330.000 rows, so every ms counts..
I only have to select the urls for products staring with "tbproduct_" objectid.
My query:
SELECT seo2.oxseourl, seo2.oxobjectid, seo2.oxparams
FROM oxseo AS seo2
JOIN (
SELECT oxobjectid,
MAX(oxparams) AS maxparam
FROM oxseo
GROUP BY
oxobjectid
) AS usm
ON usm.maxparam = seo2.oxparams
WHERE seo2.oxobjectid LIKE '%tbproduct_%'
AND seo2.oxparams REGEXP '^-?[0-9]+$'
But this returns the same rows for the products.
Thanks for any help.

A bit optimized, and a lot faster:
SELECT seo.oxseourl, seo.oxobjectid, MAX(seo.oxparams)
FROM oxseo AS seo
WHERE seo.oxobjectid LIKE 'tbproduct_%' AND seo.oxparams REGEXP '^-?[0-9]+$'
GROUP BY seo.oxseourl, seo.oxobjectid

Related

Pick only the first value in an IF statement inside a WHERE clause

I have a query like this:
... WHERE ... AND (IF(category.discount_value > 0, product_sizes.product_price * (1-category.discount_value/100),
IF(sub_category.discount_value > 0,product_sizes.product_price * (1-sub_category.discount_value/100),
IF(discount.product_id = product.id AND discount.from_date < now() AND discount.to_date >= now() AND discount.status = 1, product_sizes.product_price * (1-discount.percent/100),product_sizes.product_price)
)
)) >= 100 ...
Note that this is a part of the query, it is a long query so I'm trying to make it simpler to understand my problem.
And consider the table product_sizes:
product_id | price
1 | 50
1 | 110
Basically, I'm checking for a discount on the category, if there's no discount, I check if there's one for the subcategory, and finally if the item itself has a discount if both are false.
The problem is, I want the to take the first item (with price 50) when using product_sizes.price in the code here and use it as the maximum/minimum value so in this case it won't show up in the result, but it is now taking the last one instead most of the times.
I tried to add an alias, but then I can't use that alias in the WHERE clause, and the HAVING clause solution ignores GROUP BY so it is also not working.
Also, a subquery can't use a value from the parent query so it won't work for me. I'm using a product.id given by the query itself too.
I hope you can understand what's the issue. I'm looking for something like a function or something to use like this FIRST_V(product_sizes.product_price).
Thanks in advance.
select price from (select product_id,min(price) as price from product_sizes group by product_id)

SQL:Show column only if has data in it

Suppose I have a table like this:
name | age | experience
abc | 18 | 0
def | 19 | 0
efg | 20 | 0
I want to select the experience column only if any one value is greater than zero.
In this case, my SQL query should return only name and age and not experience.
If experience of lets say "efg" is greater than 0, then query should return name, age and experience.
I have tried following query
SELECT EXISTS (SELECT name,age,experience FROM emp_info )
AND NOT
EXISTS (SELECT experience FROM emp_info WHERE experience=0 );
But it is not working.
Try this:-
IF ((select max(experience)FROM emp_info) > 0)
SELECT name,age,experience FROM emp_info
ELSE
SELECT name,age FROM emp_info
In almost all relational databases, your queries have to return fixed numbers of columns, i.e the same number of columns for all rows. So what you are asking for isn't reasonable. You could probably get something like this to work on Informix due to jagged tables support, but that's the only one I can think of.
Other options you have include serializing to JSON in your query, or generating XML but that's a bit advanced for this and it is not clear this is what you want.
Normally we handle this on the front end, not in the database query.
SELECT name, age, NULLIF(experience, 0) from emp_info
Your question is kind of tricky because returning different set of column depending on the result is maybe not what you want to do, you could do it directly from your code, not from your SQL projection.
This may work :
if(experience > 0)
begin
SELECT name,age,experience FROM emp_info
end
else
begin
SELECT name,age FROM emp_info
end

SQL stament groups rows and calculate average

I am stuck with the following issue. I have 1 table that looks like this:
field_number.. Value
````````````````````````````````
1 ......................... 1
2 ..........................1
3 ......................... 2
4 ..........................2
etc.
I want to group different fieldnumbers and have an average for the value column. So the output should be:
field_number................Value
name(1,2)...................... 1.............. ((1+1)/2)
name(3,4)...................... 2.............. ((2+2)/2)
I have checked previous questions but cannot find any question that covers this issue (I might search on the wrong keywords though). So if this has already been covered my appologies, but any help or a point to a previous answer would be appreciated.
** =============UPDATE============= **
I went through your suggestions but did not get it right. So I am trying to be more specific. I almost have the result I want apart from the fact I want to have a fixed value in one of my columns. I have the following query:
Select
Avg(wp_rg_lead_detail.value),
wp_rg_lead_detail.field_number,
From
wp_rg_lead_detail
Where
wp_rg_lead_detail.field_number In (15, 17, 24) A
UNION
Select
Avg(wp_rg_lead_detail.value),
wp_rg_lead_detail.field_number,
From
wp_rg_lead_detail
Where
wp_rg_lead_detail.field_number In (16, 108, 18)
etc.
This gives me a table with two columns
wp_rg_lead_detail.value................field_number
4.3 (average)..............................15 (first value of av calculation)
What I want is to change the field number (15 in this case) in a fixed value (text). What and how should I add this to the query?
SELECT avg(value) FROM table WHERE field_number in (1,2)
SELECT avg(value) FROM table WHERE field_number in (3,4)
If your table is really this simple, you can also get away with:
select distinct
Value,
count(Value) as '#'
from table_name
group by Value
If you acctually want to group by a range, than you can put the logic of the range in your grouping clause (see this fiddle)
select distinct
avg(Value) as average,
floor(Value),
count(Value) as '#'
from table_name
group by floor(Value)
In the fiddle I used grouping on whole integers, but you can make that as complex as you like (see, for instance, this example)
If you are actually also interested in your corresponding fields, use group_concat() like so
select
Value,
group_concat(
distinct field_number
order by Value
) as fields
from table_name tn1
group by Value
order by Value
output:
Value | fields
---------------------------------
1 | 1,2
2 | 3,4
See this fiddle implemented from this blog post
For a generalized answer.
SELECT CONCAT('name','(',GROUP_CONCAT(field_number),')') AS field_number,
AVG(Value) as Value
FROM table_name
group by table_name.`Value`
Hope this helps.

MySQL MAX from count query

I have table rozpis_riesitelov which contains columns :
id_rozpisu_riesit, id_zam, id_projektu, id_ulohy.
I made query :
select id_zam, id_ulohy, count(*) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)
which shows me id of employee (id_zam) and how many times He was in project (id_ulohy is irrevelant but I had to select it beacuse of having clause). It shows me everyone in db but I am looking for employee with ID of 4 who is in 6 projects (Yes, I could do order by but I want to see max). When I do max of this query like this:
select max(counted)
from (select id_zam, id_ulohy, count(id_zam) as counted
from rozpis_riesitelov
group by id_zam
having id_ulohy in (1,2,8)) as riesitel
which shows me number 149 instead of 6.
So basically I only need to find employee that occurs in the most of the projects.
What's wrong with sorting by the COUNT() value, and limiting to one result?
SELECT `id_zam`,
`id_ulohy`,
COUNT(*) AS `counted`
FROM `rozpis_riesitelov `
WHERE `id_ulohy` IN ( 1, 2, 8 )
GROUP BY `id_zam`
ORDER BY `counted` DESC
LIMIT 1
Not sure exactly what you are trying to accomplish but you only use HAVING to filter on your aggregate like this:
HAVING COUNT(*) > 1
you should be able to move the condition to a WHERE clause and get correct max returned:
select max(counted)
from (select id_zam, count(id_zam) as counted
from rozpis_riesitelov
where id_ulohy in (1,2,8)
group by id_zam) as riesitel

MYSQL retrieve data dependent on rows returned

I am working on a mysql query that will filter out certain occurrences dependent on how many rows are returned.
I am trying to filter out any support categories when the number of rows returned are 1, however leave the support category in when the result set turned is more than 1.
I originally had this idea however it seems as if it will not work.
SELECT stockmaster.description, SUM(salesorderdetails.quantity), stockmaster.categoryid as qty
FROM salesorderdetails, stockmaster
where salesorderdetails.stkcode=stockmaster.stockid
and orderno='5222'
group by stockmaster.description
HAVING CASE WHEN stockmaster.categoryid = 'S&M' THEN COUNT(*) >= 2 ELSE COUNT(*) = 1 END
Any help will be gratefully accepted.
Try this
SELECT *
FROM
(
SELECT stockmaster.description,
SUM(salesorderdetails.quantity),
stockmaster.categoryid as qty ,
COUNT(*) AS count
FROM salesorderdetails, stockmaster
where salesorderdetails.stkcode=stockmaster.stockid
and orderno='5222'
group by stockmaster.description
HAVING CASE WHEN stockmaster.categoryid = 'S&M'
) MAIN_DATA
WHERE MAIN_DATA.count >1