Move SQL for View Into Manageable Chunks - sql

I have the following code in SQL:
SELECT
(SELECT Form_Title
FROM Forms
WHERE Form_ID = (SELECT TOP 1 Form_ID
FROM [Form_Responses]
WHERE [Form_Response_ID] = [Form_Response_ID])) AS Form_Name
FROM
[FooDb].[dbo].[Submissions]
In essence, I am selecting data three tables "away" and nesting all these selections. So I select a field from one table, and use it to make selection in another.
I can't use vars in a view, so how do I make this remotely readable?
Edit - the pseudocode below is what I was going for with the SQL above and it works, but I don't know how to make it clean, and that's the question:
//Form_Response_ID exists on Submissions
SELECT Get_Query_Result(Form_Response_ID) as Form_Name
FROM Submissions
Get_Query_Result(Form_Response_ID)() {
return SELECT Form_Title FROM Forms WHERE Form_ID = Get_Form_Id(Form_Response_ID);
}
// Form_Responses has Form_Response_ID as well
Get_Form_Id(Form_Response_ID) {
return SELECT TOP 1 Form_ID FROM [Form_Responses] WHERE [Form_Response_ID] = Form_Response_ID
}

Most likely the query you are looking for is like below
select f.Form_Title as Form_Name
from
Forms f JOIN Form_Responses fr
on f.Form_ID=fr.Form_ID
JOIN Submissions s
on fr.Form_Response_ID=S.Form_Response_ID

Related

Dynamic SQL Case statement?

I have a table that is called DefaultCountries.
It contains the following columns:
CountryID INT
DefaultCountryID INT
CountryRank INT
I have 29 different countries with varying data for each country. For example:
CountryID of 1 has 2 records:
CountryID of 7 has 3 records
I have a table variable #CountryData that I'm trying to join to that currently has data for CountryIDs 1 and 10.
I would like to be able to match up to the DefaultCountryID found in the DefaultCountries table. So if I pass in CountryID = 1, I could do something like:
SELECT TOP 1 DefaultCountryID
WHERE CountryID = 1 -- that is my simple case.
Where I'm having an issue is where there are more than 2+ rows. As in my example for CountryID = 7. Basically I want to have something where if there is no records in my table that I'm trying to join to with the 1st record (CountryRank = 1) then I would like it to search for the next record.
So searching for CountryID = 7, then if nothing, then CountryID = 10 (so on and so forth).
I've tried different variations of this LEFT JOIN
SELECT *
FROM #CountryData cd
LEFT JOIN DefaultCountries dc ON dc.defaultCountryid = cd.CountryID
AND cd.CountryID = 7
But this just brings back all the data (1 & 10). Do I have to use a loop to do this the way I'm describing? I thought about a CASE statement as well, but since I could have more than 2+ in the DefaultCountries table I'm not sure how I could keep searching.
I tried doing an IN statement, but I have 2 issues there. I can't do an order by in the IN statement as I get the following message:
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified.
And even if there is a way to make sure I'm searching in the order I want using an IN statement, I want to make sure it stops searching on the 1st one it finds. So to expand on my example, if table (#CountryData) table now contains records where CountryID = 7 and CountryID = 10 I only want to return the records where CountryID = 7.
If i'm following you right you can just use a CTE
with cte as(
select
CountryID,
DefaulteCountryID,
ROW_NUMBER() over (partition by CountryID order by CountryRank) as rn
from DefaultCountries
where DefaultCountryID in (select distinct CountryID from #CountryData))
Then just join to this cte where rn = 1
So this would satisfy "Basically I want to have something where if there is no records in my table that I'm trying to join to with the 1st record (CountryRank = 1) then I would like it to search for the next record" meaning if there wasn't a 1 you'd get 2, or 3, or what ever the next order number is.

How to efficiently write DISTINCT query in Django with table having foreign keys

I want to show distinct cities of Users in the front end dropdown. For that, i make a db query which fetches distinct city_name from table City but only those cities where users are present.
Something like below works for a small size of User table, but takes a very long time if User table in of size 10 million. Distinct cities of these users are still ~100 though.
class City(models.Model):
city_code = models.IntegerField(unique=True)
city_name = models.CharField(max_length=256)
class User(models.Model):
city = models.ForeignKey('City', to_field='city_code')
Now i try to search distinct city names as:
City.objects.filter().values_list('city__city_name').distinct()
which translates to this on PostgreSQL:
SELECT DISTINCT "city"."city_name"
FROM "user"
LEFT OUTER JOIN "city"
ON ("user"."city_id" = "city"."city_code");
Time: 9760.302 ms
That clearly showed that PostgreSQL was not making use of index on 'user'.'city_id'. I also read about a workaround solution here which involved writing a custom SQL query which somehow utilizes index.
I tried to find distinct 'user'.'city_id' using the above query, and that actually turned out to be pretty fast.
WITH
RECURSIVE t(n) AS
(SELECT min(city_id)
FROM user
UNION
SELECT
(SELECT city_id
FROM user
WHERE city_id > n order by city_id limit 1)
FROM t
WHERE n is not null)
SELECT n
FROM t;
Time: 79.056 ms
But now i am finding it hard to incorporate this in my Django code. I still think it is a kind of hack adding custom query in the code for this. But a bigger concern for me is that the column name can be totally dynamic, and i can not hardcode these column names (eg. city_id, etc.) in the code.
#original_fields could be a list from input, like ['area_code__district_code__name']
dataset_klass.objects.filter().values_list(*original_fields).distinct()
Using the custom query would need atleast splitting the field name with '__' as delimiter and process the first part. But it looks like a bad hack to me.
How can i improve this?
PS. The City User example is just shown to explain the scenario. The syntax might not be correct.
I finally reached to this workaround solution.
from django.db import connection, transaction
original_field = 'city__city_name'
dataset_name = 'user'
dataset_klass = eval(camelize(dataset_name))
split_arr = original_field.split("__",1)
"""If a foreign key relation is present
"""
if len(split_arr) > 1:
parent_field = dataset_klass._meta.get_field_by_name(split_arr[0])[0]
cursor = connection.cursor()
"""This query will run fast only if parent_field is indexed (city_id)
"""
cursor.execute('WITH RECURSIVE t(n) AS ( select min({0}) from {1} '
'union select (select {0} from {1} where {0} > n'
' order by {0} limit 1) from t where n is not null) '
'select n from t;'.format(parent_field.get_attname_column()[1], dataset_name))
"""Create a list of all distinct city_id's"""
distinct_values = [single[0] for single in cursor.fetchall()]
"""create a dict of foreign key field to the above list"""
"""to get the actual city_name's using _meta information"""
filter_dict = {parent_field.rel.field_name+'__in':distinct_values}
values = parent_field.rel.to.objects.filter(**filter_dict).values_list(split_arr[1])
else:
values = dataset_klass.objects.filter().values_list(original_field).distinct()
Which utilizes the index on city_id in user table, runs pretty fast.

How do I write this query to get back what I need?

I'm trying to write a query that will retrieve some columns (what a surprise!). I'm horrible with anything other than simple queries and especially in Access. Below is an image of the query designer in Access.
The fields at the bottom are the fields I am looking to pull back. The project_master.ContactDesigner is the foreign key to contacts.ContactID. I want to get a list of the MilestoneNames for ID's 2, 3 and 4. Then say for example, MilestoneID 2 has a MilestoneName of Project Initiation, I want to have a record for as many projects that exists that have a start and end date in the project_milestone_dates for that MilestoneID and list the Names of the contacts for each record that are tied to the foreign key project_master.ContactDesigner. This needs to grab only the records that have a ProjectPriority of 2 for example.
Not sure if this is clear as it's very hard for me to explain what I'm looking for here but I am missing criteria or maybe even some IDs I need to add to the query? I'm so lost. The current design returns nothing in the columns.
SELECT milestone_def.milestonename,
contacts.firstname,
priority_def.priorityname,
project_milestone_dates.startdate,
project_milestone_dates.enddate,
milestone_def.milestonedefid
FROM (project_milestone_dates
INNER JOIN (priority_def
INNER JOIN (contacts
INNER JOIN project_master
ON ( contacts.contactid =
project_master.contactdesigner ))
ON priority_def.prioritydefid =
project_master.projectpriority)
ON project_milestone_dates.projectid =
priority_def.prioritydefid)
INNER JOIN milestone_def
ON project_milestone_dates.milestoneid =
milestone_def.milestonedefid
WHERE ( ( ( project_master.projectpriority ) = [#priority] )
AND ( ( milestone_def.milestonedefid ) = 5
OR ( milestone_def.milestonedefid ) = 6
OR ( milestone_def.milestonedefid ) = 7 ) );
Changed it to 5 Or 6 Or 7 as that's what it should be.
Edit*
I've removed line AND (contacts.ContactID = project_master.ContactOwner) as I did not need that in the query.
project_milestone_dates.ProjectID = priority_def.PriorityDefID
That looks like a bad join.
Shouldn't it be?:
project_milestone_dates.ProjectID = priority_def.projectid
Move the project_milestone_date table so that it connects directly to project_master, and not to priority_def

How to get one common value from Database using UNION

2 records in above image are from Db, in above table Constraint are (SID and LINE_ITEM_ID),
SID and LINE_ITEM_ID both column are used to find a unique record.
My issues :
I am looking for a query it should fetch the recored from DB depending on conditions
if i search for PART_NUMBER = 'PAU43-IMB-P6'
1. it should fetch one record from DB if search for PART_NUMBER = 'PAU43-IMB-P6', no mater to which SID that item belong to if there is only one recored either under SID =1 or SID = 2.
2. it should fetch one record which is under SID = 2 only, from DB on search for PART_NUMBER = 'PAU43-IMB-P6', if there are 2 items one in SID=1 and other in SID=2.
i am looking for a query which will search for a given part_number depending on Both SID 1 and 2, and it should return value under SID =2 and it can return value under SID=1 only if the there are no records under SID=2 (query has to withstand a load of Million record search).
Thank you
Select *
from Table
where SID||LINE_ITEM_ID = (
select Max(SID)||Max(LINE_ITEM_ID)
from table
where PART_NUMBER = 'PAU43-IMB-P6'
);
If I understand correctly, for each considered LINE_ITEM_ID you want to return only the one with the largest value for SID. This is a common requirement and, as with most things in SQL, can be written in many different ways; the best performing will depend on many factors, not least of which is the SQL product you are using.
Here's one possible approach:
SELECT DISTINCT * -- use a column list
FROM YourTable AS T1
INNER JOIN (
SELECT T2.LINE_ITEM_ID,
MAX(T2.SID) AS max_SID
FROM YourTable AS T2
GROUP
BY T2.LINE_ITEM_ID
) AS DT1 (LINE_ITEM_ID, max_SID)
ON T1.LINE_ITEM_ID = DT1.LINE_ITEM_ID
AND T1.SID = DT1.max_SID;
That said, I don't recall seeing one that relies on the UNION relational operator. You could easily rewrite the above using the INTERSECT relational operator but it would be more verbose.
Well in my case it worked something like this:
select LINE_ITEM_ID,SID,price_1,part_number from (
(select LINE_ITEM_ID,SID,price_1,part_number from Table where SID = 2)
UNION
(select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 1 and line_item_id NOT IN (select LINE_ITEM_ID,SID,price_1,part_number from Table SID = 2)))
This query solved my issue..........

LINQ to Entity, joining on NOT IN tables

My brain seems to be mush right now! I am using LINQ to Entity, and I need to get some data from one table that does NOT exist in another table.
For example: I need the groupID, groupname and groupnumber from TABLE A where they do not exist in TABLE B. The groupID will exist in TABLE B, along with other relevant information. The tables do not have any relationship. In SQL it would be quite simply (there is a more elegant and efficient solution, but I want to paint a picture of what I need)
SELECT
GroupID,
GroupName,
GroupNumber,
FROM
TableA
WHERE
GroupID NOT IN (SELECT GroupID FROM TableB)
Is there an easy/elegant way to do this using the Entity Framework/LINQ to Entity?
Right now I have a bunch of queries hitting the db, then comparing, etc. It's pretty messy.
You could use any
var temp =context.TableA
.Where(x=>!context.TableB.Any(y=>y.GroupID!=x.GroupID))
.Select(x=>new { GroupID = x.GroupID, GroupName=x.GroupName, GroupNumber = x.GroupNumber}).ToList();
It depends upon how you've met them, which you don't show, but, generally:
var q = from a in Context.TableA
where !a.Group.TableBs.Any()
select new
{
GroupID = a.GroupID,
GroupName = a.GroupName,
GroupNumber = a.GroupNumber
};
#Nix - Your result set should have been either:
var temp =context.TableA
.Where(x=>context.TableB.Any(y=>y.GroupID != x.GroupID))
.Select(x=>new { GroupID = x.GroupID, GroupName=x.GroupName, GroupNumber = x.GroupNumber}).ToList();
Or
var temp =context.TableA
.Where(x=> ! context.TableB.Any(y=>y.GroupID == x.GroupID))
.Select(x=>new { GroupID = x.GroupID, GroupName=x.GroupName, GroupNumber = x.GroupNumber}).ToList();
But NOT both, like you wrote it.