How to use an excludent IN? - mysql

I have the following code:
SELECT stores_tb.stores, sum(products_tb_tb.prices)
from products_tb
inner join stores_tb
on products_tb.id_store = stores_tb.id_store
where products_tb.barcode IN ($barcodes)
group by stores_tb.stores
order by sum(products_tb.prices)
Being the $barcodes an array (already converted to a string) that I receive via ajax in a php file that executes the MySQL.
The thing is that the IN is inclusive, using OR for each of the array values, meaning that if one of the stores required on the SELECT have one, but not all of the barcodes in the array, it will be shown.
I wanna know if there is a function like the IN (or a way to use the IN function) in which it will return only the stores that have all of the barcodes passed in the array, the equvilant of using AND instead of OR for each of the array values.

You can do this with a having clause:
select s.stores, sum(p.prices)
from products_tb p join
stores_tb s
on p.id_store = s.id_store
where p.barcode IN ($barcodes)
group by s.stores
having count(distinct p.barcode) = $n -- the number of codes that need to match
order by sum(p.prices);
The $n value is the length of the $barcodes list (strictly speaking, the number of unique items in it).

Instead of an array and an IN clause You could use a subselect and the ALL operator
SELECT stores_tb.stores, sum(products_tb_tb.prices)
from products_tb
inner join stores_tb
on products_tb.id_store = stores_tb.id_store
where products_tb.barcode = ALL (
select barcode from my_table )
)
group by stores_tb.stores
order by sum(products_tb.prices)
https://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
https://dev.mysql.com/doc/refman/5.7/en/all-subqueries.html

Related

Unable to write WHERE condition for a JSON array field with array values in MySQL

I have a JSON datatype with array values in a MySQL database as highlighted in the picture below:
I want to compare multiple values with this category field, Ex: ["49","27"].
How to write a MySQL query for this?
I tried this query:
SELECT l.*, pc.name as cat_name,u.name as uname
FROM listing l
LEFT OUTER JOIN package_purchased_history ph ON ph.user_id = l.user_id AND ph.expired_date >= 1656095400 AND ph.purchase_date <= 1656095400
LEFT OUTER JOIN user u ON u.id = l.user_id
INNER JOIN category pc ON JSON_SEARCH(l.categories, 'one', pc.id) AND pc.parent = 26
WHERE JSON_CONTAINS(l.categories,'["49"]','$[0]') IS NOT NULL
AND l.status = 'active'
GROUP BY l.id
Unfortunately it is not working, so please suggest me the a better approach.
$[0] is the first element of the array, not the whole array. So you're testing whether an array is contained in a single number, not whether the array is contained in the array.
The whole array is $, since that refers to the top-level element of the JSON value. But you don't need to specify the path when you're searching the whole value.
WHERE JSON_CONTAINS(l.categories, '[49]')
You don't need IS NOT NULL there, since JSON_CONTAINS() returns a boolean. The value will never be NULL unless l.categories is NULL.

mysql create a hardcoded value within select statement

I want to know if I can hardcode a value within my select statement. I have the following mysql query that I use to generate a list.
I use concat to build this string as part of creating the list.
However, now I need to generate an 'Unknown' record as part of the list.
For example:
20(ABC Object #20)
24(DEF Object #24)
I want to add a value of 'UKNOWN' to the top of the list:
--(UNKNOWN -- )
20(ABC Object #20)
24(DEF Object #24)
Here is what I have so far:
SELECT CAST(p.Serial AS UNSIGNED INTEGER) as Serial,
p.Object_ID,
p.Part_ID,
st.Description AS ObjectDesc,
s.Object_Num,
concat(Serial,' (',st.Desc,' #',s.Object_Num,')') as DropList
FROM Parts p LEFT JOIN Objects s ON p.Object_ID = s.Object_ID
LEFT JOIN ObjectTypes st ON s.ObjectType_ID = st.ObjectType_ID
Can I hardcode that string in my select statement? If so, how do I do that?
If I understand correctly, you want a new row. You can use UNION
SELECT "" as Serial,
"" as Object_ID,
"" as ObjectDEsc,
"" as Object_Num,
"--(UNKNOWN -- )" as DropList
UNION
SELECT CAST(p.Serial AS UNSIGNED INTEGER) as Serial,
p.Object_ID,
p.Part_ID,
st.Description AS ObjectDesc,
s.Object_Num,
concat(Serial,' (',st.Desc,' #',s.Object_Num,')') as DropList
FROM Parts p LEFT JOIN Objects s ON p.Object_ID = s.Object_ID
LEFT JOIN ObjectTypes st ON s.ObjectType_ID = st.ObjectType_ID
In a union query each part must select the same columns. Since your original query included Serial, Object_ID, Part_ID and ObjectDesc, the first part must include it as well.

MySql dynamic column name

[major edit to make things clear]
I want to write a query that returns a dynamic column name like this:
SELECT
f2 AS
(
SELECT column_name
FROM column_names_tbl
WHERE column_name = "experience"
limit 0,1
)
FROM some_table
so that would output the same as this:
SELECT
f2 AS experience
FROM some_table
This is no correct SQL syntax, even because the two queries (the selected field and it's alias) are both subqueries and unrelated to each other. So, there's also no possibility for mysql to distinguish what name you want to connect to what value, even if the syntax was correct...
You already use a more or less normalized relational table, so I suggest the following solution:
you select the revision ID and name in a separate query; store them in PHP and use them for whatever you want
next, you evaluate the following query into a separated result set: SELECT ps.keyname, psv.keyvalue FROM page_setting_values AS psv INNER JOIN page_settings AS ps ON ps.id = psv.setting_id WHERE psv.page_revision_id = :revision with :revision representing your revision id
you may now assemble an associated array from that result set:
$settings = [];
$result = $db->executeQuery('...')->fetchAll();
foreach($result as $setting)
{
$settings[$setting['keyname']] = $setting['keyvalue'];
}
Hope that helps ;)

How to pass data dynamically to mysql query

I have following query,
SELECT t_subject.subject, SUM( t_skilllist.skill_level ) AS total_skill, t_users.first_name,
t_skilllist.skill_level
FROM `t_skilllist`
JOIN t_subject ON t_subject.id = t_skilllist.subject_id
JOIN t_users ON t_users.id = t_skilllist.user_id
WHERE t_subject.subject = 'html'
GROUP BY t_users.first_name
ORDER BY total_skill DESC
LIMIT 0 , 30
I want to display subject and skill level for each student. But, for one subject I can do that with above query. As an example for html it works. However, I want to pass more than one subject to the query dynamically. I tried to combined subjects with AND operator but it return empty result set.
How to solve this? How to pass more than two subjects to the query? I am using PHP as server side scripting language.
You can use the IN() clause.
WHERE t_subject.subject IN ('html', 'php', 'and', 'a', 'lot', 'more')

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 –