MySQL best select multi condition query - mysql

I have a MySQL query:
SELECT * FROM product_variants WHERE (bottom_type = '$bottom_type1' OR bottom_type = '$bottom_type2' ) AND (bottom_size = '$bottom_size ' ) AND (product_id != '$product_id1 ' OR product_id != '$product_id2' OR product_id != '$product_id3')
It is not working as it should, its not giving me the results needed.
What is the best way to build it?
Thanks

This is just my guess at what you're after. Example table structure, with data and expected results would help answer your question.
SELECT *
FROM product_variants
WHERE bottom_type IN ('$bottom_type1', '$bottom_type2')
AND bottom_size = '$bottom_size'
AND product_id NOT IN ('$product_id1 ', '$product_id2', '$product_id3')

Related

database query to get lowest price based on last crawel date

I would like to get lowest price of product based on last crawled dates by various resellers. My current function is very basic, it gets me lowest price from table without considering reseller ids and crawled timestamps.
I've rough idea that we can SELECT * FROM "custom_data_table" and process the data using php. Please have a look at attachment for further clarification.
function get_lowest_price($table_id) {
global $wpdb;
$table_prices = $wpdb->get_results(
$wpdb->prepare(
"SELECT price FROM `custom_data_table` WHERE tableid= %d"
,$table_id)
);
if (!empty($table_prices) && $table_prices !== NULL)
return rtrim(min($table_prices)->price, '00');
}
The right query here is:
SELECT price
FROM custom_data_name cdn, (
SELECT MAX(crawled) AS maxCrawled, resellerid
FROM custom_data_name
GROUP BY resellerid
) cdnFiltered
WHERE cdn.crawled = cdnFiltered.maxCrawled AND
cdn.resellerid = cdnFiltered.resellerid AND
tableid = %d;
Try this:
SELECT B.price
FROM (SELECT resellerid, MAX(crawled) max_crawled
FROM custom_data_table
GROUP BY resellerid) A
JOIN custom_data_table B
ON A.resellerid=B.resellerid AND A.max_crawled=B.crawled;
Maybe use ORDER BY crawled and LIMIT 1

SQL substring Issue ( Where substring(...) = (select....) )

I'm trying to search only the dirname from full path using this queries.
SELECT
`file_name` FROM `tbl_files` where SUBSTR(`file_path`,
LOCATE('/',`file_path`)+1,
(CHAR_LENGTH(`file_path`) - LOCATE('/',REVERSE(`file_path`)) - LOCATE('/',`file_path`))) =
(Select `source_path` from `tbl_transcode_folder` where `trancode_folder_id` = 1 )
But it return me nothing. When i replace (Select source_path from tbl_transcode_folder where trancode_folder_id = 1 ) into it's result mnt/hd/1 like the queries below , It's response want i to but i dont want to do in that way.
SELECT
`file_name` FROM `tbl_files` where SUBSTR(`file_path`,
LOCATE('/',`file_path`)+1,
(CHAR_LENGTH(`file_path`) - LOCATE('/',REVERSE(`file_path`)) - LOCATE('/',`file_path`))) = `mnt/hd/1`
Right now your sub-query returns a random row from the table you need to define a relation between the tbl_transcode_folder table, you need to define a relation between the outer query and the sub-query to make them correlated
SELECT `file_name`
FROM `tbl_files`
where SUBSTR(`file_path`, LOCATE('/',`file_path`)+1
,(CHAR_LENGTH(`file_path`) - LOCATE('/',REVERSE(`file_path`))
- LOCATE('/',`file_path`)))
=(Select `source_path`
from `tbl_transcode_folder`
where `trancode_folder_id` = 1
AND `tbl_files`.`CommonColumn` = `tbl_transcode_folder`.`CommonColumn`)

Query performance with OR

Maybe this is a basic question, but haven't been able to answer it, and would appreciate your help :)
I have the following table in MySQL:
create table anotation
(
chromosome enum
(
'Chr1',
'Chr2',
'Chr3',
'Chr4',
'Chr5',
'ChrC',
'ChrM'
),
version varchar(10),
type enum
(
'CDS',
'chromosome',
'exon',
'five_prime_UTR',
'gene',
'mRNA',
'mRNA_TE_gene',
'miRNA',
'ncRNA',
'protein',
'pseudogene',
'pseudogenic_exon',
'pseudogenic_transcript',
'rRNA',
'snRNA',
'snoRNA',
'tRNA',
'three_prime_UTR',
'transposable_element_gene'
),
strand enum
(
'+',
'-'
),
phase tinyint,
atrributes text
);`
And it has around 600,000 values, and I'm doing the following query:
select distinct
anot_1.chromosome,
anot_1.start,
anot_1.end,
anot_1.atrributes
from
anotation anot_1,
anotation anot_2
where
anot_1.type='CDS'
and
anot_2.type='protein'
and
anot_1.chromosome!='ChrM'
and
anot_1.chromosome!='ChrC'
and
anot_1.chromosome=anot_2.chromosome
and
(
(
anot_2.start=anot_1.start
and
anot_1.end!=anot_2.end
and
anot_2.strand='+'
)
or
(
anot_2.start!=anot_1.start
and
anot_1.end=anot_2.end
and
anot_2.strand='-'
)
);
And in it takes a long while to finish, acutally, but when I do the query (same one, but I drop the one of the conditions from the OR ) it runs almost instantely:
select distinct
anot_1.chromosome,
anot_1.start,
anot_1.end,
anot_1.atrributes
from
anotation anot_1,
anotation anot_2
where
anot_1.type='CDS'
and
anot_2.type='protein'
and
anot_1.chromosome!='ChrM'
and
anot_1.chromosome!='ChrC'
and
anot_1.chromosome=anot_2.chromosome
and
anot_2.start=anot_1.start
and
anot_1.end!=anot_2.end
and
anot_2.strand='+';`
Anyone has any idea of whats happening and if so, how can I solve it?
Thank you!!!
This isn't a solution (and I agree with comments above about indexes), but I have changed your SQL around to use a pair of left outer joins rather than your current SQL which has an OR in the JOIN.
While I don't expect this to be much different in performance it might help you and others see what the query is doing:-
SELECT distinct anot_1.chromosome, anot_1.start, anot_1.end, anot_1.atrributes
FROM anotation anot_1,
LEFT OUTER JOIN anotation anot_2 ON anot_1.chromosome = anot_2.chromosome AND anot_1.start = anot_2.start AND anot_1.end != anot_2.end AND anot_2.strAND = '+' AND anot_2.type='protein'
LEFT OUTER JOIN anotation anot_3 ON anot_1.chromosome = anot_3.chromosome AND anot_1.end = anot_3.end AND anot_1.start != anot_3.start AND anot_3.strAND = '+' AND anot_3.type='protein'
WHERE anot_1.type = 'CDS'
AND anot_1.chromosome != 'ChrM'
AND anot_1.chromosome != 'ChrC'
AND (anot_2.chromosome IS NOT NULL
OR anot_3.chromosome IS NOT NULL)
I'd start by sanitising your query in general, breaking them apart and doing a union
select
CDS.chromosome,
CDS.start,
CDS.end,
CDS.atrributes
from
(
select
a.chromosome,
a.start,
a.end,
a.attribures,
from
anotation a,
where
a.type='CDS'
and
not a.chromosome IN ('ChrM', 'ChrC')
) CDS
join
(
select
a.strand,
from
anotation a,
where
a.type='protien'
) Protien
on
CDS.chromosome = Protien.chromosome
and
CDS.start = Protien.start
and
CDS.end != Protien.end
where
Protien.strand = '+'
union
select
CDS.chromosome,
CDS.start,
CDS.end,
CDS.atrributes
from
(
select
a.chromosome,
a.start,
a.end,
a.attribures,
from
anotation a,
where
a.type='CDS'
and
not a.chromosome IN ('ChrM', 'ChrC')
) CDS
join
(
select
a.strand,
from
anotation a,
where
a.type='protien'
) Protien
on
CDS.chromosome = Protien.chromosome
and
CDS.start != Protien.start
and
CDS.end = Protien.end
where
Protien.strand = '-'

mysql error: sub-query returns more than 1 row

I am using two tables here projections_report p and access_rights a. I can't find out why I am getting the error:
subquery returns more than one row
(case when paramChannel='AllC' then p.gl_sal_chan in
(case when dc_lob=0 then (select distinct pr.gl_sal_chan from
projections_report pr) else (select distinct pr1.gl_sal_chan
from projections_report pr1 where pr1.gl_sal_chan
in (select distinct a.gl_sal_chan from access_rights
a where a.userid= paramUserId)) end)
else p.gl_sal_chan = paramChannel end)
I tried using all and any keywords. Please help.
Thanks in advance.
USE LIMIT in sub queries to return only one record as you are using distinct, it might return more than one record
I tried to do it in another way and got it right. Firstly I changed the statement in else condition of second case statement to
(select distinct gl_sal_chan from access_rights where userid = paramUserid)
as both return the same result(my bad) and secondly I changed the entire condition to
(case when (paramChannel = 'AllC' && dc_lob = 0) then '%' = '%' else
(case when (paramChannel='AllC' && dc_lob != 0) then
gl_sal_chan in (select distinct gl_sal_chan from access_rights where userid = paramUserid)
else gl_sal_chan= paramChannel end)end)
Anyway Thanks #all :)

SQL - Make this statement faster i.e. less duration, reads

Given the following tables:
Orders (OrderID, OrderStatus, OrderNumber)
OrderItems(OrderItemID, OrderID, ItemID, OrderItemStatus)
Orders: 2537 records
Order Items: 1319 records
I have created indexes on
Orders(OrderStatus)
OrderItems(OrderID)
OrderItems(OrderItemStatus)
I have the following SQL statement (generated by LinqToSql) which when executed, has:
- duration = 8789
- reads = 7809.
exec sp_executesql N'SELECT COUNT(*) AS [value]
FROM [dbo].[Orders] AS [t0]
WHERE ([t0].[OrderStatus] = #p0) OR (EXISTS(
SELECT NULL AS [EMPTY]
FROM [dbo].[OrderItems] AS [t1]
WHERE ([t1].[OrderID] = [t0].[OrderID]) AND ([t1].[OrderItemStatus] = #p1)
))',N'#p0 nvarchar(2),#p1 nvarchar(2)',#p0=N'KE',#p1=N'KE'
Is there anything else which I can do to make it faster?
make all those nvarchars parameters varchars if the columns in the table are varchars
))',N'#p0 varchar(2),#p1 varchar(2)',#p0=N'KE',#p1=N'KE'
See also here: sp_executesql causing my query to be very slow
Count on a single index rather than *
This might generate some better sql.
IQueryable<int> query1 =
from oi in db.OrderItems
where oi.OrderItemStatus == theItemStatus
select oi.OrderID;
IQueryable<int> query2 =
from o in db.Orders
where o.OrderStatus == theOrderStatus
select o.OrderID;
IQueryable<int> query3 = query1.Concat(query2).Distinct();
int result = query3.Count();