Double AND Where Clause with between Dates - mysql

I currently have a query like this
WHERE Category = 'Freezing' OR Category ='Ooredoo FTTH fault'OR Category ='Ooredoo TT fault ' OR Category ='No Picture'
but i want use this date search query with the above code,
im able to use any 1 of this code but im unable to use both query, i have used "AND" or "OR" But its Not working,
ScheduleDate BETWEEN '".$_POST["from_date"]."' AND '".$_POST["to_date"]."' ```

a or b or c and d is ambiguous. You need to use parenthesis to make it explicit how to group the ands and ors. If you want category to match ANY of the options AND the schedule is between certain dates. (a or b or c) and d.
where (
Category = 'Freezing' or
Category = 'Ooredoo FTTH fault' or
Category = 'Ooredoo TT fault ' or
Category = 'No Picture'
)
and ScheduleDate BETWEEN ? AND ?
(Note: Do not use string concatenation to put values into queries, especially not straight from user input. It's a security hole and can cause errors. Use bind parameters.)
(Note: You have an extra space in one of your options.)
You can also use in to make the query simpler.
where
Category in (
'Freezing', 'Ooredoo FTTH fault', 'Ooredoo TT fault', 'No Picture'
)
and ScheduleDate BETWEEN ? AND ?

Related

Difference between "and not ()" and "and (... not like ...)"?

I receive completely different results from my query depending on where I put NOT. Can you please explain the difference?
Below is the first way:
SELECT COUNT(*)
FROM [table]
WHERE condition = 'N'
AND (Category NOT LIKE '%str1%'
OR Category NOT LIKE '%str2%'
OR Category NOT LIKE '%str3%')
The second way:
SELECT COUNT(*)
FROM [table]
WHERE condition = 'N'
AND NOT (Category LIKE '%str1%'
OR Category LIKE '%str2%'
OR Category LIKE '%str3%')
Both seem the same for me.
You need to change the operators within the parentheses to AND, if you add NOT, which will impact adversly all the terms within parentheses, such as
SELECT count(*)
FROM[table]
WHERE condition = 'N'
AND NOT (Category LIKE '%str1%'
AND Category LIKE '%str2%'
AND Category LIKE '%str3%')
A OR B equals NOT ( A AND B ) in Boolean logic
I just want to note that you can simplify this logic:
WHERE condition = 'N' AND
Category NOT REGEXP 'str1|str2|str3'
This eliminates issues with parentheses and the placement of the NOT.

ORDER BY field when using table joins

I've got a products table that I'm trying to get to work. The query brings back results; however, it isn't actually using the ORDER BY FIELD to sort the results. It's skipping it somehow. I even tried ORDER BY FIELD(sc.id,'4','5','6'), and that didn't work either.
Is it even possible to use table_name.column in an ORDER BY FIELD()? Is there an alternative or a better method of doing this query?
$product = $db1q->query("
SELECT p.id, p.name, p.image, p.url,p.subcat as subcat, sc.id as scid,sc.name as scname
FROM Product as p
JOIN Product_Sub_Category as sc ON p.subcat = sc.id
WHERE p.visibility='1' AND find_in_set(p.id,'". $sidr['products'] ."')
ORDER BY FIELD(p.subcat,'4','5','6'), sc.sort_order ASC, p.sort_order ASC")
or die ('Unable to execute query. '. mysqli_error($db1q));
I just dumbed the query down to the basic level....
$product = $db1q->query("
SELECT id, name, image, url,subcat
FROM Product WHERE visibility='1' AND id IN ({$sidr['products']}) ORDER BY FIELD(subcat,'5','4','6','22')") or die ('Unable to execute query. '. mysqli_error($db1q));
and for some reason the order of my subcats are as follows....
3,12,23,5,5,4,4,4,4,4,22
Why wouldn't they begin with 5, 4, 6(doesn't exist), and 22? Then display 3,12, and 23 after those are first....
Simple Rextester Demo
When datatype is numeric don't compare to 'string' values
eg visibility = '1' if visibility is numeric you really shouldn't have the apostrophes around it. same in the field function given subcat.
$product = $db1q->query("SELECT id, name, image, url,subcat
FROM Product
WHERE visibility='1'
AND id IN ({$sidr['products']})
ORDER BY case when subcat in (5,4,6,22) then 0 else 1 end,
FIELD(subcat,5,4,6,22)
") or die ('Unable to execute query. '. mysqli_error($db1q));
or something like:
order by case when field(sort,'5','4','22') = 0 then (select max(sort)+1+sort from Product)
else field(sort,'5','4','22') end;
The issue with the 2nd approach is that it has to run a subquery for every record. In addition if the size of subcat/sort exceed or approach the max of int we'll run into a problem adding the values together. This problem is negated by using the 2 column sort approach in the first method.
Again, my gut feeling is that the first approach with 2 sort columns would be faster; and in my opinion easier to follow/maintain. The downfall is if the sort order defined changes then we have to change code. So... why have the order defined here... what isn't the order defined in a table; or is the order passed in as a parameter by user?

WHere clause taking much longer time

HI i am using this query below its taking hell lot of a time around like 5 mins .. its crazy .. any better way ? or reason fr such long time .. even cutting it into smaller query n getting the value n then finding the common values is much much faster then this.
SELECT Product_ItemID
FROM Product_ItemProperties
LEFT JOIN Product_Items USING (Product_ItemID)
WHERE
Product_CatalogueID = 'xx' AND
Field = 'brandname' AND
MATCH (Value) AGAINST ('xx' IN BOOLEAN MODE) AND
Product_ItemID IN (Select Product_ItemID
FROM Product_ItemProperties
Where Field = 'xx' AND
Match (Value) AGAINST ('xx' IN BOOLEAN MODE)
);
i dont know why in first where clause you are making Field = 'brandname' and in second inner where clause you are filtering by Field = 'xx' . anyway you are double selecting Product_ItemProperties while you should use it once.
try this:
SELECT
Product_ItemID
FROM
Product_ItemProperties
LEFT JOIN
Product_Items USING (Product_ItemID)
WHERE
Product_CatalogueID = 'xx'
AND Field = 'brandname'
AND MATCH (Value) AGAINST ('xx' IN BOOLEAN MODE)
AND Field = 'xx';
It looks like your itemProperties table has multiple entries for the same "Product_ItemID", and you are looking for something that is both "BrandX", AND has some "OtherProperty" of a different value. To handle this, you can use that table TWICE (or more if more property values you are interested in... I would suggest having an index on your Product_ItemProperties table by (Product_ItemID, Field, Value) to be best optimization of the query.
For example, you are looking for a Car Brand "X", and secondly, it is a "Blue" car (not considering the catalog component).
Also, notice in this query, I give simplified aliases, and qualify each field with the alias.field so there is no ambiguity which field is coming from where.
The outer WHERE clause is your first criteria, only get those items that have a minimum of the brand name field, and it matches the value you are expecting... From those, join again to the product item properties table, but for the "other" field value you are interested in, and its value.
I was unsure where the cataglog component was, but I suspect that's from the product table and should have ITs alias adjusted.
SELECT
ByBrand.Product_ItemID,
P.NameOfProduct, (just an example to get this too)
FROM
Product_ItemProperties ByBrand
JOIN Product_Items P
ON ByBrand.Product_ItemID = P.Product_ItemID
JOIN Product_ItemProperties ByOtherField
ON ByBrand.Product_ItemID = ByOtherField.Product_ItemID
AND ByOtherField.Field = 'otherPropertyInterestedIn'
AND MATCH (ByOtherField.Value) against ( 'otherValueLookingFor' IN BOOLEAN MODE )
WHERE
ByBrand.Product_CatalogueID = 'someCatalogID' (or is this from product_items table)
AND ByBrand.Field = 'brandname'
AND MATCH (ByBrand.Value) against ( 'brandValueLookingFor' IN BOOLEAN MODE )

MYSQL - want to select some rows, sometimes the field won't be there, but i want to use a WHERE on that field when it is there

ok this is hard to explain...
i have the following tables:
table : words
table: word_progress
table: word_set
foreign keys:
words.id = word_set.word_id
word_progress.word_id = words.id
word_progress.user_id = users.id
basically a word is in a word_set. word_progress (it keeps score on a certain word) relates to a user_id and word_id.
the problem is sometimes there is not an entry in word_progress for user_id and word_id. but when it IS there, i wanna be able to use word_progress in the WHERE part of the query. but if it is not there I dont. My work around at the moment is before running the statement, i do an "insert IGNORE IF EXISTS into work_progress (word_id,user_id) values (?,?)" to make sure its there
i have this query
select
words.* ,
word_progress.progress from words
left join word_progress on word_progress.word_id = words.id
left join word_set on word_set.id = words.word_set_id
where word_set.id = ? and word_progress.user_id = ?
but... the problem is sometimes there is no word_progress entry for that word
how can i do this?
you're already left-joining, so when there's no data available, you'll just get null as value for your word_progress-fields. just check for that like this:
...
and
(
word_progress.user_id is null
or
word_progress.user_id = ?
)
another way would be to add the user-restriction directly to the join-criteria like this:
...
left join word_progress
on word_progress.word_id = words.id
and word_progress.user_id = ?
...
and drop that criteria from the where-part.
note that, in both cases, you'll have to handle the null-cases for progress later in your code properly.
yeah, this is ambiguous: " i wanna be able to use word_progress in the WHERE part of the query. but if it is not there I dont. "
in the left joins,
if there's no word_progress to match a word, you'll still get a result row for the word, it's just that all the fields of word_progress will be null.
Same for word_set: no corresponding word_set, then word_set.id and all the rest are null.
so include 'is null' or 'is not null' in your where clause depending on what you want.... think about that case, that's what you left ambiguous. or remember that 'a = b' is false if either a or b is null (even if they're both null), so design your where clause to fit.

Linq Group on a multi-level object with select statement

I've got 3 dataset objects that are nested with each other using entity set objects. I am selecting the data like this
var newList = from s in MainTable
from a in s.SubTable1 where a.ColumnX = "value"
from b in a.Detail where b.Name = "searchValue"
select new {
ID = s.ID,
Company = a.CompanyName,
Name = b.Name,
Date = s.DueDate
Colour = b.Colour,
Town = a.Town
};
and this works fine, but the trouble is there are many records in the Detail object-list/table for each Name value so I get a load of duplicate rows and thus I only want to display one record per b.Name. I have tried putting
group s by b.Name into g
before the select, but then this seems to stop the select enabling me to select the columns I want (there are more, in practice). How do I use the group command in this circumstance while still keeping the output rows in a "flat" format?
Appending comment as answer to close question:-
Of course that if you group your results, you cant get select a column of a child, thats because there may be more than one childs and you have to specify an aggregate column for example the sum,max etx –