Unique records in search query including many to one subquery - ms-access

First time poster and enthusiastic Access newbie.
I've got a search screen based on Allen Browne's wonderful search in vba (http://allenbrowne.com/ser-62.html). This has worked great for most of my purposes, but now a child table is duplicating records.
Our clients(providers), can be enrolled in multiple programs. we've got four. I want a search that let's me filter by provider type, but not create duplicate records when a provider is enrolled in more than one provider type. In the example image, carmen titus is in the LEHRC and fccn programs, and therefore shows up twice. Tried to post pic but no dice.
Please help! I searched diligently and could not find a solution. I'd appreciate the support or to be pointed to a related post. I hope this makes sense. I think half my battle as a self-trained newbie is not knowing the terminology.

We'll need more info!
It sounds like the query you are basing the search on contains columns from two tables with a one to many relationship ie clients and "Client programs", such that a single client has zero to 4 programs.
It sounds like you only want to return a list of providers (ie rows on the one side), but your SQL is returning data from both tables.
Here's what you SQL might need to look like to do what you need:
SELECT *
FROM clients AS mainClient
WHERE
EXISTS
(SELECT 1
FROM clients AS C
LEFT JOIN ClientPrograms AS CP
ON C.ID = CP.ClientID
WHERE mainClient.ID = C.ID
' the above line links the EXISTS "Sub query" to the main query
AND client name like "*j*" ... etc...
... ie lots of criteria generated by you popup search criteria dialogue)
)
By adding the EXISTS statement the main query will be editable.
If you had used SQL like the following you would not be able to edit it
SELECT c.name, c.dob, etc.. ie all the field you want on the form whichwill all be from the client table
FROM clients AS C
LEFT JOIN ClientPrograms AS CP
ON C.ID = CP.ClientID
WHERE mainClient.ID = C.ID
' the above line links the EXISTS "Sub query" to the main query
AND client name like "*j*" ... etc...
... ie lots of criteria generated by you popup search criteria dialogue)
GROUP BY all the field in the select statement
I hope this gives you some inspiration

Related

MySQL 1:N Data Mapping

Something really bugs me and im not sure what is the "correct" approach.
If i make a select to get contacts from my database there are a decent amount of joins involved.
It will look something like this (around 60-70 columns):
SELECT *
FROM contacts
LEFT JOIN company
LEFT JOIN person
LEFT JOIN address
LEFT JOIN person_communication
LEFT JOIN company_communication
LEFT JOIN categories
LEFT JOIN notes
company and person are 1:1 cardinality so its straight forward.
But "address", "communication" and "categories" are 1:n cardinality.
So depending on the amount of rows in the 1:n tables i will get a lot of "double" rows (I don't know whats the real term for that, the rows are not double i know that the address or phone number etc is different). For myself as a contact, a fairly filled contact, i get 85 rows back.
How do you guys work with that?
In my PHP application i always wrote some "Data-Mapper" where the array key was the "contact.ID aka primary" and then checked if it exists and then pushed the additional data into it. Also PHP is not really type strict what makes it easy.
Now I'm learning GO(golang) and i thought screw that LOOOONG select and data mapping just write selects for all the 1:n.... yeah no, not enough connections to load a table full of contacts. I know that i can increase the connections but the error seems to imply that this would be the wrong way.
I use the following driver: https://github.com/go-sql-driver/mysql
I also tried GROUP_CONCAT but then i running in trouble parsing it back.
Do i have to do my mapping approach again or is there some nice solution out there? I found it quite dirty at points tho?
The solution is simple: you need to execute more than one query!
The cause of all the "duplicate" rows is that you're generating a result called a Cartesian product. You are trying to join to several tables with 1:n relationships, but each of these has no relationship to the other, so there's no join condition restricting them with respect to each other.
Therefore you get a result with every combination of all the 1:n relationships. If you have 3 matches in address, 5 matches in communication, and 5 matches in categories, you'd get 3x5x5 = 75 rows.
So you need to run a separate SQL query for each of your 1:n relationships. Don't be afraid—MySQL can handle a few queries. You need them.

PHP / MySQL selecting records from multiple tables

i have a MySQL statement which works - i can get the records requested - movies.* & groups.name.
$stmt= $mysqli->query("SELECT DISTINCT ebooks.*, groups.name FROM ebooks
INNER JOIN ebooks_groups ON ebooks.uuid = ebooks_groups.ebookuuid
INNER JOIN groups_users ON ebooks_groups.groupuuid = groups_users.groupuuid
INNER JOIN groups ON groups_users.groupuuid = groups.uuid
WHERE useruuid=".$get_useruuid."
ORDER BY groups.name");
1/ However i need to grab another column from the groups table - namely groups.uuid
i tried
SELECT DISTINCT movies.*, groups.* FROM movies, groups
&
SELECT DISTINCT movies.*, groups.name, groups.uuid FROM movies, groups
but it retrieved no records.
2/ Then I had another look at my original code - ... FROM movies ... - how is this even working if i'm not selecting FROM movies, groups tables?
AFAIK, this is pure MySQL. PHP or not doesn't come into play.
First to understand is the implicit join:
Explicit vs implicit SQL joins
That understanding should solve at least half of your problem.
Secondly, I'd never code a SELECT * without a very good reason (and there's few). It makes much more sense to select just the columns you need instead of getting them all and even if you need all that are currently there, if you work on the database model later on, there might be more (or less!!) columns in the database and it'll be much harder to detect that your code needs updating if you don't have them explicitly listed.
For the rest I build my SQL queries slowly step by step. That helps a lot to debugging your queries esp. as you have the actual tables and some sample data ...
[That should solve your other half of the question]

How to represent Cross Apply and Split String in MySQL

For some background, what i'm trying to do create a database that contains multiple recipes. However, it's necessary for the individual ingredients to be linked to the recipe they originally came from.
For instance, I have table containing all the individual ingredients.
And a table where the recipes are stored, minus the ingredients.
Now, i've found this article which covers how to split strings using T-SQL XML Commands, and the code that is used to do so is:
SELECT
Books.BookId,
Books.Book,
BookAuthors.AuthorId,
BookAuthors.Author
FROM Books
CROSS APPLY dbo.split(Books.Authors,',') split
INNER JOIN BookAuthors ON BookAuthors.AuthorId = split.val
The result i'm looking for would be very similar to this:
However, CROSS APPLY etc only works on MS SQL Server and my question is:
Is it possible to achieve the same, or very similar effect using MySQL?
Thanks for any help.
This should quite match what you're trying to get:
SELECT
Books.BookId,
Books.Book,
BookAuthors.AuthorId,
BookAuthors.Author
FROM Books
LEFT JOIN BookAuthors ON (find_in_set(BookAuthors.AuthorId, Books.Authors) <> 0)
Found this article very helpful: MySQL query finding values in a comma separated string
Leave a comment if you need further explanation how it works.

MySQL query - single product with multiple reviews

Thank you in advance for any help you may be able to offer!
I'm working with an a bit of an odd database where products are related via tags and are not hierarchical.
I'm trying to select a single product using a SKU number from a table and join it with a table of product reviews like so:
SELECT ims.master_sku, ims.title, ims.price,
ims.description, ir.mvp_number, ir.title,
ir.review, ir.rating, ir.created_on
FROM default_inventory_master_skus AS ims
JOIN default_inventory_reviews AS ir
WHERE ims.master_sku = '22284319'
GROUP BY ir.review;
This gives me around 150 rows - which are all the same product but contain different reviews. My question is how can I return just the one product (as a single row) and somehow convert the reviews into columns associated with that one product?
Again - thank you for your time and help.
Rich
You can do that, although it's not "relational".
Looks like someone wants this data in Excel ;).
With MySQL, you will need to generate an SQL statement and execute it. Either within MySQL (in a procedure) or outside (e.g., in PHP). Query first for the pivot column names, put together the statement, then execute it.
An idea of the implementation is here:
http://www.artfulsoftware.com/infotree/queries.php#78

Filter a MySQL Result in Delphi

I'm having an issue with a certain requirement to one of my Homework Assignments. I am required to take a list of students and print out all of the students with credit hours of 12 or more. The Credit hours are stored in a separate table, and referenced through a third table
basically, a students table, a classes table with hours, and an enrolled table matching student id to Course id
I used a SUM aggregate grouped by First name from the tables and that all works great, but I don't quite understand how to filter out the people with less than 12 hours, since the SQL doesn't know how many hours each person is taking until it's done with the query.
my string looks like this
'SELECT Students.Fname, SUM(Classes.Crhrs) AS Credits
FROM Students, Classes, Enrolled
WHERE Students.ID = Enrolled.StudentID AND Classes.ID = Enrolled.CourseID
GROUP BY Students.Fname;'
It works fine and shows the grid in the Delphi Project, but I don't know where to go from here to filter the results, since each query run deletes the previous.
Since it's a homework exercise, I'm going to give a very short answer: look up the documentation for HAVING.
Beside getting the desired result directly from SQL as Martijn suggested, Delphi datasets have ways to filter data on the "client side" also. Check the Filter property and the OnFilter record.
Anyway, remember it is usually better to apply the best "filter" on the database side using the proper SQL, and then use client side "filters" only to allow for different views on an already obtained data set, without re-querying the same data, thus saving some database resources and bandwidth (as long as the data on the server didn't change meanwhile...)