Optimized Query in T-SQL - sql

This is commonly faced problem, if you are developing any software solution for any government department. So consider this as critical question to be addressed.
Understanding the scenario
Every government as departments, departments in different cities and each of those are responsible for serving the needs of citizen services. For example, Industry Commiserate. If you want to establish a new manufacturing unit for some products, You are supposed to apply to government department, officials carry out scrutiny and other required verification process. At the end get decision that whether you are eligible for establishing a unit.
Meeting Requirements
To meet above requirement we created database... I'm not going to include everything here but only required tables.
1. GovtOfficers: Goverment officers details having fields
DeptOfficers: contains Department officers,
Citizens: are people like us who file applications,
Applications: are applications submitted by citizen
ApplicationAction: are action taken on different applications...
Now, Our purpose is to find Last Status and Officer name working on particular application...
We'll write it like,
Select *
from Applications A
inner join Citizens C on A.CitizenId=C.Id
left join ApplicationAction AC on A.Id=AC.ApplicationId
left join
(
Select max(Id)
from ApplicationAction
group by ApplicationId
) X on AC.Id=X.Id
The above query fetches the required result and works fine.... But it does not when the data out grows up to 10-20 Lacks, It starts taking time and eventually may timeout.
What could be better approach?
OK, Based on experience gained, I can add ActionId in Application Table as well which will store most recent action taken on that table.... and can solve my problem.
The problem is, I can use above mentioned solution for upcoming projects.. Not the projects that I have completed or I don't have contract.
So I'm not looking for schema change anyway to optimize above query.

do the null application separate
select * from
( Select *,
row_number() over(partition by AC.ApplicationId order by AC.id desc) as rn
from Applications A
join Citizens C
on A.CitizenId = C.Id
join ApplicationAction AC
on A.Id = AC.ApplicationId
) ttt
where ttt.rn = 1

Related

Retrieve the most recent person record added to an account

I am trying to build a table of Contact IDs (Primary Keys) of the most recently created records assigned to each Account of a certain type in our Salesforce org.
Working in Salesforce Marketing Cloud, I'm trying to build a sample list that I can setup to update automatically so the records I'm testing against are never stale. I only need one example from each account to do my testing. Since I want to make sure the record isn't stale, I want to select the most recent record assigned to each Account.
Every Contact is assigned to one and only one Account. The Account ID lives as a foreign key on the Contact Record. The created date of the Contact is also a field on the Contact record.
The Sample list needs to contain the email address, ContactID, and the name of the Management Company, which lives on the Account record.
I figured doing a directional JOIN toward the Account table would do the trick, but that didn't work. I figure that's because there's nothing distinguishing which record to pick.
This is what I've got for code, which is pretty useless...
SELECT
C.Email AS Email,
C.Id AS Id18,
C.AccountID AS AccountID,
A.Management_Company AS ManagementCompany
FROM
ENT.Contact_Salesforce_DE AS C
RIGHT JOIN ENT.Account_Salesforce_DE AS A ON C.AccountID = A.Id
WHERE
A.RecordTypeId = '1234567890ABCDEFGH' AND
A.Management_Company IS NOT NULL AND
C.Email IS NOT NULL
The syntax checks out, but I get a system error every time I run it.
Marketing Cloud runs on an older version of SQL Server, so some more recent query functions won't always work.
And yes, I'm a relative noob to SQL. Won't surprise me if this has a really simple solution, but I couldn't find another entry describing the solution, so...
If I followed you correctly, you want to pull out the latest contact associated with each account.
On database servers that do not support window function (which seems to be the case of your RDBMS), one typical solution is to add a special condition to the JOIN. This NOT EXISTS condition uses a subquery to ensure that the record being picked in the child table is the most recent one (in other words : there is no child record with a highest creation date than the one being joined) :
SELECT
c.Email AS Email,
c.Id AS Id18,
c.AccountID AS AccountID
FROM
ENT.Account_Salesforce_DE AS a
INNER JOIN ENT.Contact_Salesforce_DE AS c
ON c.AccountID = a.Id
AND c.email IS NOT NULL
AND NOT EXISTS (
SELECT 1
FROM ENT.Contact_Salesforce_DE AS c1
WHERE
c1.email IS NOT NULL
AND c1.AccountID = a.Id
AND c1.CreatedDate > c.CreatedDate
)
WHERE
A.RecordTypeId = '1234567890ABCDEFGH'
AND A.Management_Company IS NOT NULL

What is a SQL Server data structure to represent several objects chained together?

Suppose I have two tables in a SQL Server database: dbo.Companies and dbo.Contracts.
Suppose that I want to represent a one-to-one relationship between companies and contracts to indicate that a contract has been awarded to a company. I would simply create a join table with a foreign key to dbo.Companies and dbo.Contracts.
The above scenario is easy for any experienced SQL developer.
Suppose then, that I want to do something similar, but each company to which a contract is awarded can subcontract out to another company, which can subcontract out further.
I might have a company called "Acme", which might subcontract to "Evil Geniuses", which might subcontract to "Evil on a Budget".
Or then again, I "Acme" might subcontract to "Evil Geniuses" which subcontracts to "Evil on a Budget, but "Acme" might simultaneously subcontract another portion of the same contract to "Falling Anvils".
One must bear in mind that a company may be involved in many, many different contracts at different levels, or there may be companies in the system that are awarded no contracts at all.
What sort of data structure allows me to describe these relationships in SQL?
Edit: I am using MS SQL Server.
The same as a one-to-one (or one-to-many) relationship is sufficient.
SQL allows for recursive traversal of such relationships.
I have not tested the following query, but it should give you a basic idea.
WITH RECURSIVE ContractHolders AS (
SELECT * FROM dbo.Companies AS m
JOIN dbo.Contracts AS n ON m.id = n.ContractHolderId
WHERE m.name = 'Acme'
UNION ALL
SELECT m.* FROM ContractHolders AS h
JOIN dbo.Companies AS m ON m.id = h.ContractRecipientId
JOIN dbo.Contracts AS n ON m.id = n.ContractHolderId
)
SELECT * FROM ContractHolders;
I guess you use Microsoft SQL Server based on your use of dbo. Read Recursive Queries Using Common Table Expressions for more information.
I would use the contracts table like:
contract_id primary key,
company_id foreign key (companies.company_id),
parent_id foreign key (contracts.contract_id),
*** contract_level,
*** contract details
contract_level is optional here, depending on the business requirements. The largest drawback of this query is the inability of finding the top-level owner of the contract in one query. This can be solved in adding a column like contract_family equalling contract_id of the top-level contract. The query to view all the chain will be like:
select * from contracts
left join companies on contracts.company_id = companies.company_id
where contract_family = ...
order by contract_level

How can I improve a mostly "degenerate" inner join?

This is Oracle 11g.
I have two tables whose relevant columns are shown below (I have to take the tables as given -- I cannot change the column datatypes):
CREATE TABLE USERS
(
UUID VARCHAR2(36),
DATA VARCHAR2(128),
ENABLED NUMBER(1)
);
CREATE TABLE FEATURES
(
USER_UUID VARCHAR2(36),
FEATURE_TYPE NUMBER(4)
);
The tables express the concept that a user can be assigned a number of features. The (USER_UUID, FEATURE_TYPE) combination is unique.
I have two very similar queries I am interested in. The first one, expressed in English, is "return the UUIDs of enabled users who are assigned feature X". The second one is "return the UUIDs and DATA of enabled users who are assigned feature X". The USERS table has about 5,000 records and the FEATURES table has about 40,000 records.
I originally wrote the first query naively as:
SELECT u.UUID FROM USERS u
JOIN FEATURES f ON f.USER_UUID=u.UUID
WHERE f.FEATURE_TYPE=X and u.ENABLED=1
and that had lousy performance. As an experiment I tried to see what would happen if I didn't care about whether or not a user was enabled and that inspired me to try:
SELECT USER_UUID FROM FEATURES WHERE TYPE=X
and that ran very quickly. That in turn inspired me to try
(SELECT USER_UUID FROM FEATURES WHERE TYPE=X)
INTERSECT
(SELECT UUID FROM USERS WHERE ENABLED=1)
That didn't run as quickly as the second query, but ran much more quickly than the first.
After more thinking I realized that in the case at hand every user or almost every user was assigned at least one feature, which meant that the join condition was always or almost always true, which meant that the inner join completely or mostly degenerated into a cross join. And since 5,000 x 40,000 = 200,000,000 that is not a good thing. Obviously the INTERSECT version would be dealing with many fewer rows which presumably is why it is significantly faster.
Question: Is INTERSECT really the way go to in this case or should I be looking at some other type of join?
I wrote the query for the one that also needs to return DATA similarly to the very first one:
SELECT u.UUID, u.DATA FROM USERS u
JOIN FEATURES f ON f.USER_UUID=u.UUID
WHERE f.FEATURE_TYPE=X and u.ENABLED=1
But it would seem I can't do the INTERSECT trick here because there's no column in FEATURES that matches the DATA column.
Question: How can I rewrite this to avoid the degenerate join problem and perform like the query that doesn't return DATA?
I would intuitively use the EXISTS clause:
SELECT u.UUID
FROM USERS u
WHERE u.ENABLED=1
AND EXISTS (SELECT 1 FROM FEATURES f where f.FEATURE_TYPE=X and f.USER_UUID=u.UUID)
or similarly:
SELECT u.UUID, u.DATA
FROM USERS u
WHERE u.ENABLED=1
AND EXISTS (SELECT 1 FROM FEATURES f where f.FEATURE_TYPE=X and f.USER_UUID=u.UUID)
This way you can select every field from USERS since there is no need for INTERSECT anymore (which was a rather good choice for the 1st case, IMHO).

Needing 2 different ID's from the same ID Table

I am pulling reports for my company and am needing to pull a specific report that I am having trouble with. We are using SQL Server 2012 and I am pulling the SQL reports.
What I need is to pull a simple report:
Group Name, List of Members in the group; Supervisor of the group.
However, the problem is that the supervisor as well as the members and the group name all come from one table in order to get the relevant information. Currently here is my SQL code below:
Use DATABASE
go
-- This is the select portion deciding the columns needed.
select
C.group_name
,C2.first_name
,C2.last_name
-- These are the tables that the query is pulling from.
FROM db..groups AS G
LEFT OUTER JOIN db..contact AS C
ON G.group_id=C.contact_id
INNER JOIN db..contact AS C2
ON G.member=C2.contact_id
go
This pulls the first portion:
The group name, then the first name of a member in that group, and then the last name of a member in that group.
However, I am having trouble getting the supervisor portion. This portion uses the table db.contact under the column supervisor_id as a foreign key. The supervisor_id uses the same unique id as the normal contact_id, but in the same table. Some contact_ids have supervisor_id's that are other contact_id's from the same table, hence the foreign key.
How can I make it so I can get the contact_id that is equal to the supervisor_id of the contact_id that is equal to the group_id?
Taking a quick stab at this while we wait for details
You know you need groups and I'm assuming you don't care about Groups that have no members. Thus Groups INNER JOINed to Contact. This generates your direct group membership. To get the supervisor, you then need to factor in the Supervisor on the specific Contact row.
You might not have a boss, or your boss might be yourself. It's always interesting to see how various HR systems record this. In my example, I'm assuming the head reports to no one instead of themselves.
SELECT
G.group_name
, C.first_name
, C.last_name
-- this may produce nulls depending on outer vs inner join below
, CS.first_name AS supervisor_first_name
, CS.last_name AS supervisor_last_name
FROM
dbo.Groups AS G
INNER JOIN
dbo.Contact AS C
ON C.contact_id = G.member
LEFT OUTER JOIN
dbo.Contact AS CS
ON CS.contact_id = C.supervisor_id;
Depending on how exactly you wanted that data reported, there are various tricks we could use to report that data. In particular, GROUPING SETS might come in handy.
SQLFiddle

How to make this relation in PostgreSQL?

Hello.
As shown in the ER model, I want to create a relation between "Busses" and "Chauffeurs", where every entity in "Chauffeurs" must have at least one relation in "Certified", and every entity in "Busses" must have at least one relation in "Certified".
Though it was pretty easy to design the ER model, I can't seem to find a way of making this relation in PostgreSQL. Anybody got some ideas ?
Thanks
The solution should be database agnostic. If I understand you correctly, you probably want your certified table to look like:
CERTIFIED
id
bus_id
chauffer_id
...
...
The only solution I've been able to find is the notion of a single mandatory field in the parent table to represent the "at least one" and then storing the 2 or more relationships in the intersection table.
chauffeurs
chauffeur_id
chauffer_name
certified_bus_id (not null)
certified
chauffer_id
bus_id
busses
bus_id
bus_name
certified_chauffer_id (not null)
To get a list of all busses where a chauffer is certified becomes
select c.chauffer_name, b.bus_name
from chauffeurs c
inner join busses b on (b.bus_id = c.certified_bus_id)
UNION
select c.chauffer_name, b.bus_name
from chauffeurs c
inner join certified ct on (c.chauffeur_id = ct.chauffer_id)
inner join busses b on (ct.bus_id = b.bus_id)
The UNION (vs UNION ALL) takes care of deduplication with the values in certified.