Best approach to embed subquery results - sql

Currently I have a web application (JSF 2.0 and SQL Server) where values for tDataTable are retrieved using a Query A and then based on retrieved result we run another query to retrieve associated details.
for example :
Query A: returns all Restaurants in User selected Area (let's imagine there are 1000s)
Query B: Based on Returned Result (Above) , Query B retries reviews for each restaurant using the RestaurantPK value.
So the way it's done now, if there are 200 rows once Query A has executed, We call Query B 200 Times to retrieve review information for each restaurant.
So my question is how can i make more efficient? What is the standard practice in these cases? I chose the title as "Best approach to embed Sub-query result" as i suspect a sub-query will need to be used in Query A , but cannot figure out how it would work, given for each restaurant(Row) there could be 10-15 reviews).
UPDATE:
I had tried JOIN before posting my question here but problem was i was only getting one review for each restaurant instead of all available reviews for each restaurant. I'm starting to think the only way to do this would be to Write a storedProcedure where once A is executed I'll store the result in a #temp table, loop through the result and retrieve all the reviews for each restaurant and insert them back into the #temp table where if one resturant has 10 reviews, they will be separated by ; and back in java I'll split them back into a meaningful format. that way i am still returning just one row for each restaurant but with embedded reviews as one of columns.
so i would have:
Resturnat, Location, Phone......Reviews
X,Sydney,1234,.....,AAAAAAA;BBBBBBBB;CCCCCCCCC;
Comments?

Use joins in SQL, so you can get all data in 1 query.:
Select rest.id, reviews.text
from restaurants rest
inner join reviews on reviews.rest_id = rest.id
where some conditions for restaurants

You haven't said how you are 'displaying' this data so can't recommend an absolute best approach. I would say your 2 options are
A join that returns all reviews - the restaurant information will be duplicated for each row so when displaying you should loop through and check if the current row's RestaurantPK is different to the previous and only display the info then.
Return 2 tables form the SQL server. Load the results of Query A into a #temp or #temp table and then do something like
SELECT * from #temp
SELECT * FROM reviews WHERE RestaurantPK IN (SELECT RestaurantPK from #temp)
although obviously selecting your columns by name rather than *

Related

How to run sql query and loop through a column then pass that column data into another query from a second database

I am fairly new to SQL. I am using SQL Server 2014. I want to run a query on a database which returns a column of ID's. I am wondering if it is possible to loop over the column of ID's from the first database and pass them into another database to collect additional info.
Attempted to Google the answer but I'm not able to find a helpful scenario that mimics what I am looking for.
SELECT *
FROM dbo.MYDB1
WHERE CreatedLoc = 123
The above example spits out data but I only care about the ID column
I than want to loop over the ID column and for each run them on another database.
SELECT *
FROM dbo.MYDB2
WHERE ID IN (array of ids here, not hardcoded but dynamic)
Assuming appropriate permissions, you can access a different database than the one you're currently connected to using a fully qualified databasename.schemaname.tablename (or view, etc.)
If your databases are MyDB1 and MyDB2, you can run a query that looks something like this:
SELECT * from MyDB2.dbo.Table2
where ID IN (
SELECT ID from MyDB1.dbo.Table1 where CreatedLoc = 123
)

MS Access - Log daily totals of query in new table

I have an ODBC database that I've linked to an Access table. I've been using Access to generate some custom queries/reports.
However, this ODBC database changes frequently and I'm trying to discover where the discrepancy is coming from. (hundreds of thousands of records to go through, but I can easily filter it down into what I'm concerned about)
Right now I've been manually pulling the data each day, exporting to Excel, counting the totals for each category I want to track, and logging in another Excel file.
I'd rather automate this in Access if possible, but haven't been able to get my heard around it yet.
I've already linked the ODBC databases I'm concerned with, and can generate the query I want to generate.
What I'm struggling with is how to capture this daily and then log that total so I can trend it over a given time period.
If it the data was constant, this would be easy for me to understand/do. However, the data can change daily.
EX: This is a database of work orders. Work orders(which are basically my primary key) are assigned to different departments. A single work order can belong to many different departments and have multiple tasks/holds/actions tied to it.
Work Order 0237153-03 could be assigned to Department A today, but then could be reassigned to Department B tomorrow.
These work orders also have "ranking codes" such as Priority A, B, C. These too can be changed at any given time. Today Work Order 0237153-03 could be priority A, but tomorrow someone may decide that it should actually be Priority B.
This is why I want to capture all available data each day (The new work orders that have come in overnight, and all the old work orders that may have had changes made to them), count the totals of the different fields I'm concerned about, then log this data.
Then repeat this everyday.
the question you ask is very vague so here is a general answer.
You are counting the items you get from a database table.
It may be that you don't need to actually count them every day, but if the table in the database stores all the data for every day, you simply need to create a query to count the items that are in the table for every day that is stored in the table.
You are right that this would be best done in access.
You might not have the "log the counts in another table" though.
It seems you are quite new to access so you might benefit form these links videos numbered 61, 70 here and also video 7 here
These will help or buy a book / use web resources.
PART2.
If you have to bodge it because you can't get the ODBC database to use triggers/data macros to log a history you could store a history yourself like this.... BUT you have to do it EVERY day.
0 On day 1 take a full copy of the ODBC data as YOURTABLE. Add a field "dump Number" and set it all to 1.
1. Link to the ODBC data every day.
join from YOURTABLE to the ODBC table and find any records that have changed (ie test just the fields you want to monitor and if any of them have changed...).
Append these changed records to YOURTABLE with a new value for "dump number of 2" This MUST always increment!
You can now write SQL to get the most recent record for each primary key.
SELECT *
FROM Mytable
WHERE
(
SELECT PrimaryKeyFields, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
GROUP BY PrimaryKeyFields
) AS T1
ON t1.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND t1.MAXDumpNumber= Mytable.DumpNumber
You can compare the most recent records with any previous records.
ie to get the previous dump
Note that this will NOT work in the abvoe SQL (unless you always keep every record!)
AND t1.MAXDumpNumber-1 = Mytable.DumpNumber
Use something like this to get the previous row:
SELECT *
FROM Mytable
INNER JOIN
(
SELECT PrimaryKeyFields
, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
INNER JOIN
(
SELECT PrimaryKeyFields
, MAX(DumpNumber) AS MAXDumpNumber
FROM Mytable
GROUP BY PrimaryKeyFields
) AS TabLatest
ON TabLatest.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND
TabLatest.MAXDumpNumber <> Mytable.DumpNumber
-- Note that the <> is VERY important
GROUP BY PrimaryKeyFields
) AS T1
ON t1.PrimaryKeyFields = Mytable.PrimaryKeyFields
AND t1.MAXDumpNumber= Mytable.DumpNumber
Create 4 and 5 and MS Access named queries (or SS views) and then treate them like tables to do comparison.
Make sure you have indexes created on the PK fields and the DumpNumber and they shoudl be unique - this will speed things up....
Finish it in time for christmas... and flag this as an answer!

SQL query using fn_Split to find multiple values in column

This is a followup to my earlier question which got me part of the way to the goal.
Here is what I'm starting with:
SELECT * FROM MyTable WHERE County IN (SELECT value From dbo.fn_Split(#counties, ','))
Here's the scenario: In my table I've got a column named County. Each record can have multiple counties in the County column delimited with commas (I know this is bad form, I didn't do it). For example: county1, county22, county41. Some records may have only one county (say county13) others might have all the counties. So: county1, count2, county3... through county45 (yes, it's terrible, I know).
In the app I'm trying to build users can select multiple counties or even all counties in the same format as above (county1, county2, county3...). Thanks to Martin's help in the previous question I can get it to return records that have each of the counties individually but not the records that might contain all of the counties.
For example: The user selects county4, county26. I need to have the records returned that have just county4 and county26 as well as any that might contain both of them as part of a larger set (like all 45 of them).
Hope this is clear and I didn't make it more convoluted than necessary. Any assistance is very, very, very much appreciated!
To illustrate:
County
Record1 county1, county14, county26
Record2 county14
Record3 county1, county2, ... through county45
User Submission: county1, county26
Returns: Record1 and Record3
Not sure if I understood the question, but here is how I interpret it:
You need to return rows from your table for one or more selected items.
Also, you want to be able to select ALL items at once without passing the whole list.
I'd do that using Stored Procedure with 2 parameters:
#Selection SMALLINT
#TVP_County CountyTableType (It is Table Valued Variable. See: https://msdn.microsoft.com/en-us/library/bb510489.aspx)
If #Selection = 1 then you join #TVP_County with your table to get results.
If #Selection = 0 you return ALL records from your table w/o join and do not use #TVP_County at all.
If #Selection = -1 then you exclude #TVP_County items from your table. In that case you will be able to do a reverse marks. User will be able to select just few counties, which he/she does not want to see.
Of cause, within a stored procedure you have to implement the logic to run three different queries depending on the first parameter.

SQL Server 2008 Array Query

I have a table structure
ID [integer]
Name
RecoveryID [integer]
date
I want to search on the RecoveryID with an array and reveal all those in the array without a corresponding record.
so, if my table contains
1,'John',1,20-10-2013
2,'John',4,20-10-2013
3,'John',5,20-10-2013
And I search on the RecoveryID with the array [1,2,3,4,5,6] I would want the result [2,3,6]
I have tried using various IN, NOT IN statements, but I always get what I have, not what I don't have.
To try and explain further, I am trying to Outer Join without a second table. I have a list of users, a list of things that CAN be done (1,2,3,4,5,6,7) and a list of things that NEED to be done by a specific user. {[John],(1,2,7)} For example.
If John completes action 1, my work table now contains ('John',1,20-10-2013) actions 2 & 7 are remaining. I have the list (1,2,7) how can I query the work table so that it returns (2,7) ?
You can use Except set operation as :
SELECT n
FROM (VALUES(1),(2),(3),(4),(5),(6)) AS Nums(n)
EXCEPT
SELECT RecoveryID from table1

Is there any reason this simple SQL query should be so slow?

This query takes about a minute to give results:
SELECT MAX(d.docket_id), MAX(cus.docket_id) FROM docket d, Cashup_Sessions cus
Yet this one:
SELECT MAX(d.docket_id) FROM docket d UNION MAX(cus.docket_id) FROM Cashup_Sessions cus
gives its results instantly. I can't see what the first one is doing that would take so much longer - I mean they both simply check the same two lists of numbers for the greatest one and return them. What else could it be doing that I can't see?
I'm using jet SQL on an MS Access database via Java.
the first one is doing a cross join between 2 tables while the second one is not.
that's all there is to it.
The first one uses Cartesian product to form a source data, which means that every row from the first table is paired with each row from the second one. After that, it searches the source to find out the max values from the columns.
The second doesn't join tables. It just find max from the fist table and the max one from the second table and than returns two rows.
The first query makes a cross join between the tables before getting the maximums, that means that each record in one table is joined with every record in the other table.
If you have two tables with 1000 items each, you get a result with 1000000 items to go through to find the maximums.