mysql search for category from serialized array - mysql

I have a table 'users_category'
'users_category' : id, prefix, name
and table 'users'
'users' : categories, etc...
where users.categories is an array of users_category.id ids
User can be part of any category, if I stored the array of categories they are part of as a serialized array, how can I run a query to check if they are part of 'category x'
Ex:
SELECT users.*, users_category.* FROM 'users', 'users_category' WHERE users.categories='category x' AND users_category.id = 'category x'
I can't run a 'LIKE' command because the users.categories is serialized. Is their any way to search within the serialized data. Also I know that the above query may have errors

Even though normalizing the table structure is a better way to move forward but if adopting that route is not optimal at this point then you may try this query:
SELECT u.*, uc.*
FROM users u, users_category uc
WHERE uc.name='X' AND FIND_IN_SET(uc.id, u.categories)
It uses mysql function FIND_IN_SET().
Working demo available at: http://sqlfiddle.com/#!2/7f392/3

Related

Check array contain at least all value of array

I got a question about MySQL query.
I have a table role and another table context. Each role could be linked with multiple context using a join table role_context. Example:
roleA->context1
roleA->context2
roleB->context1
I want a query to get all Roles that match all context I give. Example:
If I have ['context1'] in parameter I want ['roleA', 'roleB'] in result.
If I have ['context2'] in parameter I want ['roleA'] in result.
If I have ['context1', 'context2'] in parameter I want ['roleA'] in result.
I have tried to use
SELECT *
FROM role_context
INNER JOIN context ON role_context.context_name = context.name
WHERE context.name IN ["ETT","FR"]
But like it's an in it return roleA and roleB for my third condition.
Does someone have an idea for this query?
Or maybe my SQL architecture is not good?
The architecture is OK, its just that SQL does not have built-in operators for such tasks. You can use the following query to select roles that have all contexts in the given list (must be passed as an IN clause):
SELECT role_context.role_name
FROM role_context
JOIN context ON role_context.context_name = context.name
WHERE context.name IN ('context1', 'context2')
GROUP BY role_context.role_name
HAVING COUNT(context.name) = 2 -- here 2 corresponds to the number of items in the above list

How to join document in SOLR

I have 4 CSV files which I am indexing in the same core.
PRESCRIBER.csv
Fields: PRESCRIBER_ID, PRESCRIBER_TYPE, FIRST_NAME, LAST_NAME, MIDDLE_INITIAL, DEA_NUMBER, DEA_SUFFIX, UPIN_NUMBER, SPIN_NUMBER, ACTIVE_FLAG, RESPONSIBLE_PRESCRIBER_ID, FACILITY_ID, LOCK_COL
PRESCRIBER_ADDRESS.csv
Fields: PRESCRIBER_ID, ADDRESS_ID, LOCATION_TYPE, PRIMARY_FLAG, LOCK_COL, PRESCRIBER_LOCATION_CODE
PRESCRIBER_TELEPHONE.csv
Fields: PRESCRIBER_ID, TELEPHONE_ID, PRIMARY_FLAG, LOCK_COL
TELEPHONE.csv
Fields: TELEPHONE_ID, TELEPHONE_TYPE, AREA_CODE, TELEPHONE_NUMBER, EXTENSION, LOCK_COL
I want to imitate the below SQL query in SOLR:
SELECT * FROM PRESCRIBER INNER JOIN PRESCRIBER_TELEPHONE ON
PRESCRIBER.PRESCRIBER_ID = PRESCRIBER_TELEPHONE.PRESCRIBER_ID
INNER JOIN TELEPHONE ON
PRESCRIBER_TELEPHONE.TELEPHONE_ID = TELEPHONE.TELEPHONE_ID
WHERE LAST_NAME LIKE '%A%' AND FIRST_NAME LIKE '%B%'
AND ISNULL(PRESCRIBER_TELEPHONE.PRIMARY_FLAG,'') = 'Y'
I have written the below SOLR query:
http://160.110.9.39:8983/solr/prscrbrDtls/select?q=*:*&fq=FIRST_NAME:*B*&fq=LAST_NAME:*A*&fq:{!join+from=PRESCRIBER_ID+to=PRESCRIBER_ID}TELEPHONE_ID{!join+from=TELEPHONE_ID+to=TELEPHONE_ID}PRIMARY_FLAG:Y&rows=5000
Issue:
I am only seeing the fields from PRESCRIBER.csv.
{"PRESCRIBER_ID":[XX],
"PRESCRIBER_TYPE":["MD"],
"FIRST_NAME":["ELIZABETH"],
"LAST_NAME":["CHAVEZ"],
"MIDDLE_INITIAL":["O"],
"DEA_NUMBER":["XX"],
"ACTIVE_FLAG":["X"],
"LOCK_COL":[3],
"id":"d35e4c68-9cb2-477a-ad03-7ab25bc5490d",
"_version_":1608393436695625743}
I want to see all the fields together from PRESCRIBER, PRESCRIBER_TELEPHONE and TELEPHONE in the response JSON.
Any pointers on how to do that?
Am I writing the query correct?
Additional Question:
How can I remove _str fields from SOLR response?
You're writing your query correct, but joins in Solr does not allow you to fetch anything else than what's in the primary collection you're querying. It's one of the fundamental limitations of joins in Solr.
This is different from the concept of a join in a relational database because no information is being truly joined. An appropriate SQL analogy would be an "inner query".
If you need to fetch data on multiple sides of a query, you can use a Streaming Expression, with either innerJoin, hashJoin, leftOuterJoin or one of the other join decorators. Streaming Expressions requires a fairly recent version of Solr.

SQLAlchemy foreign keys mapped to list of ids, not entities

In the usual Customer with Orders example, this kind of SQLAlchemy code...
data = db.query(Customer)\
.join(Order, Customer.id == Order.cst_id)\
.filter(Order.amount>1000)
...would provide instances of the Customer model that are associated with e.g. large orders (amount > 1000). The resulting Customer instances would also include a list of their orders, since in this example we used backref for that reason:
class Order:
...
customer = relationship("customers", backref=backref('orders'))
The problem with this, is that iterating over Customer.orders means that the DB will return complete instances of Order - basically doing a 'select *' on all the columns of Order.
What if, for performance reasons, one wants to e.g. read only 1 field from Order (e.g. the id) and have the .orders field inside Customer instances be a simple list of IDs?
customers = db.query(Customer)....
...
pdb> print customers[0].orders
[2,4,7]
Is that possible with SQLAlchemy?
What you could do is make a query this way:
(
session.query(Customer.id, Order.id)
.select_from(Customer)
.join(Customer.order)
.filter(Order.amount > 1000)
)
It doesn't produce the exact result as what you have asked, but it gives you a list of tuples which looks like [(customer_id, order_id), ...].
I am not entirely sure if you can eagerly load order_ids into Customer object, but I think it should, you might want to look at joinedload, subqueryload and perhaps go through the relationship-loading docs if that helps.
In this case it works you could write it as;
(
session.query(Customer)
.select_from(Customer)
.join(Customer.order)
.options(db.joinedload(Customer.orders))
.filter(Order.amount > 1000)
)
and also use noload to avoid loading other columns.
I ended up doing this optimally - with array aggregation:
data = db.query(Customer).with_entities(
Customer,
func.ARRAY_AGG(
Order.id,
type_=ARRAY(Integer, as_tuple=True)).label('order_ids')
).outerjoin(
Orders, Customer.id == Order.cst_id
).group_by(
Customer.id
)
This returns tuples of (CustomerEntity, list) - which is exactly what I wanted.

Join Tables with sum in sql query

It is showing Sum(with table name) is not valid. Kindly help:
Modws.DisplayDataGrid(dgvClosingBalance,
"Select
Invoice.Customer, Invoice.Sum(Total),
RptTempTable.Sum(INVOICETOTAL), RptTempTable.Sum(CNTOTAL),
RptTempTable.Sum(DEBITTOTAL), RptTempTable.Sum(RECEIPTTOTAL)
From Invoice
inner join RptTempTable on Invoice.Customer = RptTempTable.Customer")
RptTempTable.Sum(INVOICETOTAL) should be Sum(RptTempTable.INVOICETOTAL)
The same goes for the other calls to sum()
The table prefix belongs to the column name not the function call.
MySQL will accept this invalid SQL and will return "inderminate" (aka "random") values instead.
To understand the implications of MySQL's "loose" (aka "sloppy") group by implementation you might want to read these articles:
http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes-your-queries-fragile/
http://rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html

where not in select from db

I'm trying to figure out why this code doesn't work; i'm trying to select "upgrades" from the database that the user doesn't already have. I've done it two ways
This Way:
SELECT id, name, cost, prereq, nullif FROM upgrades WHERE NOT IN (Select upgrade_id FROM user_upgrades WHERE uid = :uid);
and this way:
SELECT id, name, cost, prereq, nullif FROM upgrades WHERE NOT IN (:ID)
in which the :ID tag isa list of user upgrades pulled through a function in PHP. Neither one of these codes are working--they do not show any results whats so ever.
You forgot the attribute in the condition after WHERE:
WHERE "MISSING ATTRIBUTE" NOT IN ...