Create and execute stored procedure in SQL Server - sql-server

I have four tables:
dbo.Projects (id, ProjectName, Areas, PaymentSystem, Districts.id, purpose.id, types.id, etc)
dbo.Districts(id, DistrictsName)
dbo.Purpose (id, PurposeName) - has residential & commercial
dbo.Types (id, typName)
I want to select DistrictsName where PurposeName = 'residential'
I tried this procedure :
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'
this is the result from this procedure:
ID DistrictsName PurposeName
1 District1 residential
2 District1 residential
3 District2 residential
4 District2 residential
i want display the DistrictsName without duplicate or with different values , i a have also one more project per district in projects records . this what i want to display :
ID DistrictsName PurposeName
1 District1 residential
2 District2 residential
how i get this result ,
any help is appreciated.

Why do people use stored procedures when views are much more appropriate? I have never understood this. It seems peculiar to SQL Server users.
In any case, you can do what you want with aggregation:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as id,
d.DistrictName, p.PurposeName
FROM dbo.Projects pr INNER JOIN
dbo.Purpose pu
ON pr.PurposeID = pu.ID INNER JOIN
dbo.Districts d
ON pr.DistrictID = d.ID
WHERE pu.PurposeName = N'Residential'
GROUP BY d.DistrictName, p.PurposeName;
The use of table aliases makes the query much easier to write and to read.
In addition, I don't understand the id column being output. Why would you want to construct a new id? In any case, that is what your data suggests.

Use DISTINCT statement for removing the duplicates:
CREATE PROCEDURE [dbo].[SearchResidentialProjects]
AS
SELECT DISTINCT
dbo.Projects.ID,
dbo.Districts.DistrictName,
dbo.Purpose.PurposeName
FROM
dbo.Projects
INNER JOIN
dbo.Purpose ON dbo.Projects.PurposeID = dbo.Purpose.ID
INNER JOIN
dbo.Districts ON dbo.Projects.DistrictID = dbo.Districts.ID
WHERE
dbo.Purpose.PurposeName = N'Residential'

Related

Combine 2 queries with LEFT JOIN and 3 tables

First Left JOIN with 2 tables (project_reviews & project_review_remarks)
SELECT pr.review_id,client_name,improvement_areas, strengths
FROM project_reviews pr
LEFT JOIN project_review_remarks pra ON pr.review_id = pra.review_id
WHERE review_status IN ('COMPLETED')
ORDER BY review_date DESC;
Second Left JOIN with 2 tables (project_reviews & project_review_remarks)
SELECT pr.review_id, COUNT(pra.action_item_id) AS actions
FROM project_reviews pr
LEFT JOIN project_review_action_item pra ON pr.review_id = pra.review_id
GROUP BY pr.review_id;
In both the queries, project_reviews is a common table,
IN first Query is ONE-ONE relationship
IN second Query is ONE-MANY relationship (WHERE I COUNTED it many rows using group by)
I want to merge both queries into one query, because project_reviews is a common table with review ID and show the count of action_item into one table.
Just add these code to first query.
In select add COUNT(pra.action_item_id) AS actions.
Add LEFT JOIN project_review_action_item pra ON pr.review_id = pra.review_id. Make sure that your both LEFT JOIN tables has different alias as I have updated project_review_remarksprr.
Add GROUP BY with all columns from SELECT like GROUP BY pr.review_id, client_name, improvement_areas, strengths.
To GROUP BY with TEXT columns you can cast it to VARCHAR(MAX) or NVARCHAR(MAX) whichever you think appropriate.
Check complete query below.
SELECT pr.review_id,
client_name,
CAST(improvement_areas AS VARCHAR(MAX)) AS improvement_areas,
CAST(strengths AS VARCHAR(MAX)) AS strengths,
COUNT(pra.action_item_id) AS actions
FROM project_reviews pr
LEFT JOIN project_review_remarks prr
ON pr.review_id = prr.review_id
LEFT JOIN project_review_action_item pra
ON pr.review_id = pra.review_id
WHERE pr.review_status IN ('COMPLETED')
GROUP BY pr.review_id,
client_name,
CAST(improvement_areas AS VARCHAR(MAX)),
CAST(strengths AS VARCHAR(MAX))
ORDER BY review_date DESC;

RIGHT\LEFT Join does not provide null values without condition

I have two tables one is the lookup table and the other is the data table. The lookup table has columns named cycleid, cycle. The data table has SID, cycleid, cycle. Below is the structure of the tables.
If you check the data table, the SID may have all the cycles and may not have all the cycles. I want to output the SID completed as well as missed cycles.
I right joined the lookup table and retrieved the missing as well as completed cycles. Below is the query I used.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN
[dbo].[lookup_data] s4 ON s3.CYCLEID = s4.CYCLEID
The query is not displaying me the missed values when I query for all the SID's. When I specifically query for a SID with the below query i am getting the correct result including the missed ones.
SELECT TOP 1000 [SID]
,s4.[CYCLE]
,s4.[CYCLEID]
FROM [dbo].[data] s3 RIGHT JOIN [dbo].[lookup_data] s4
ON s3.CYCLEID = s4.CYCLEID
AND s3.SID = 101002
ORDER BY [SID], s4.[CYCLEID]
As I am supplying this query into tableau I cannot provide the sid value in the query. I want to return all the sid's and from tableau I will be do the rest of the things.
The expected output that i need is as shown below.
I wrote a cross join query like below to acheive my expected output
SELECT DISTINCT
tab.CYCLEID
,tab.SID
,d.CYCLE
FROM ( SELECT d.SID
,d.[CYCLE]
,e.CYCLEID
FROM ( SELECT e.sid
,e.CYCLE
FROM [db_temp].[dbo].[Sheet3$] e
) d
CROSS JOIN [db_temp].[dbo].[Sheet4$] e
) tab
LEFT OUTER JOIN [db_temp].[dbo].[Sheet3$] d
ON d.CYCLEID = tab.CYCLEID
AND d.SID = tab.SID
ORDER BY tab.SID
,tab.CYCLEID;
However I am not able to use this query for more scenarios as my data set have nearly 20 to 40 columns and i am having issues when i use the above one.
Is there any way to do this in a simpler manner with only left or right join itself? I want the query to return all the missing values and the completed values for the all the SID's instead of supplying a single sid in the query.
You can create a master table first (combine all SID and CYCLE ID), then right join with the data table
;with ctxMaster as (
select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d
)
select d.SID, m.CYCLE, m.CYCLEID
from ctxMaster m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID
Fiddle
Or if you don't want to use common table expression, subquery version:
select d.SID, m.CYCLE, m.CYCLEID
from (select distinct d.SID, l.CYCLE, l.CYCLEID
from lookup_data l
cross join data d) m
left join data d on m.SID = d.SID and m.CYCLEID = d.CYCLEID
order by m.SID, m.CYCLEID

Sql Recursive Function only show nods that have specifik relation

I have a Link structure table with ID and parentID.
ID, Parent, name
1,1
2,1
3,2
4,3
5,3
To this table I have a structure_article relation table
in this table I have relation between a Link and a article.
struture_article
structid, articleID
4,1000
4,1001
5,1002
Every article in that table have a supplier.
Now i am trying to create a recursive function that creates the tree
nods if i pick a specific supplier.
Article table
ArticleID, SUPPLIER ID
1000,1
1001,2
1002,2
If I pick articles with supplier 1 then I want the function to show me the tree structure that have articles from that supplier.
I have 20 suppliers and 300 links in the DB now i want only to show articles from the suppliers i pick. I don want any empty nods.
Is this even possible do create with a recursive function in Sql Server version 2008?
I tyied wiht this code the problem is that i get only nods that have articles connected
WITH a
AS (SELECT *
FROM structure
WHERE parent = 125
UNION ALL
SELECT m.*
FROM structure m
JOIN a
ON m.parent = a.internidstructure)
SELECT *
FROM a
WHERE internidstructure IN (SELECT DISTINCT( internidstructure )
FROM dbo.articles
INNER JOIN dbo.structure_article
ON dbo.articles.internidarticle =
dbo.structure_article.internidarticle
WHERE ( dbo.articles.internidsupplier IN (SELECT
internidsupplier
FROM site_sup
WHERE
internidsite = 1) ))
ORDER BY parent,
sortno
Try using a left join instead of an inner join.
I'm not sure to have understood your need but if you want to have a new tree table without nodes not linked to a supplier, this query can work.
WITH A AS
(
SELECT S.ID as ID, S.Parent as Parent, 1 as art_linked
FROM structure S
INNER JOIN dbo.structure_article SA
ON S.ID = SA.structid
INNER JOIN Article AR
ON AR.ArticleID = SA.ArticleID
WHERE AR.SupplierID = 1
UNION ALL
SELECT S.ID, S.Parent, 0
FROM structure S
INNER JOIN A
ON A.parent = S.ID
WHERE S.ID <> S.Parent
)
SELECT A.ID, A.Parent, MAX(A.art_linked)
FROM A
GROUP BY A.ID, A.Parent

Need help implementing a Full Outer Join in MS Access

I'm having trouble getting a query to work properly in Access. I need a full outer join on dbo_cardpurchases and dbo_vendors so that all all vendors will appear in the query regardless of whether a purchase was made at that vendor. But Access doesn't support full outer joins. How else can I do this?
SELECT dbo_vendors.name,
Iif([fundingsourceid] = 10, [amount], "") AS Credit,
Iif(( [fundingsourceid] = 2 )
OR ( [fundingsourceid] = 3 ), [amount], "") AS EBT,
Iif([fundingsourceid] = 4, [amount], "") AS [Match],
dbo_cardpurchases.updateddate,
dbo_markets.marketid
FROM (((dbo_cardpurchases
LEFT JOIN dbo_vendors
ON dbo_cardpurchases.vendorid = dbo_vendors.vendorid)
LEFT JOIN dbo_cardfundings
ON dbo_cardpurchases.cardfundingid =
dbo_cardfundings.cardfundingid)
INNER JOIN dbo_marketevents
ON dbo_cardpurchases.marketeventid =
dbo_marketevents.marketeventid)
INNER JOIN dbo_markets
ON dbo_marketevents.marketid = dbo_markets.marketid
ORDER BY dbo_vendors.name;
As mentioned in the Wikipedia article on joins here, for sample tables
[employee]
LastName DepartmentID
---------- ------------
Heisenberg 33
Jones 33
Rafferty 31
Robinson 34
Smith 34
Williams NULL
and [department]
DepartmentID DepartmentName
------------ --------------
31 Sales
33 Engineering
34 Clerical
35 Marketing
the full outer join
SELECT *
FROM employee FULL OUTER JOIN department
ON employee.DepartmentID = department.DepartmentID;
can be emulated using a UNION ALL of three SELECT statements. So, in Access you could do
SELECT dbo_employee.LastName, dbo_employee.DepartmentID,
dbo_department.DepartmentName, dbo_department.DepartmentID
FROM dbo_employee
INNER JOIN dbo_department ON dbo_employee.DepartmentID = dbo_department.DepartmentID
UNION ALL
SELECT dbo_employee.LastName, dbo_employee.DepartmentID,
NULL, NULL
FROM dbo_employee
WHERE NOT EXISTS (
SELECT * FROM dbo_department
WHERE dbo_employee.DepartmentID = dbo_department.DepartmentID)
UNION ALL
SELECT NULL, NULL,
dbo_department.DepartmentName, dbo_department.DepartmentID
FROM dbo_department
WHERE NOT EXISTS (
SELECT * FROM dbo_employee
WHERE dbo_employee.DepartmentID = dbo_department.DepartmentID)
However, since you are using linked tables into SQL Server you can just use an Access pass-through query and perform a "real" FULL OUTER JOIN using T-SQL:
Pass-through queries always produce recordsets that are not updateable, but a native Access query against linked tables that uses UNION ALL is going to produce a recordset that is not updatable anyway, so why not take advantage of the speed and simplicity of just using SQL Server to run the query?

TSQL - Return recent date

Having issues getting a dataset to return with one date per client in the query.
Requirements:
Must have the recent date of transaction per client list for user
Will need have the capability to run through EXEC
Current Query:
SELECT
c.client_uno
, c.client_code
, c.client_name
, c.open_date
into #AttyClnt
from hbm_client c
join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
select
ba.payr_client_uno as client_uno
, max(ba.tran_date) as tran_date
from blt_bill_amt ba
left outer join #AttyClnt ac on ba.payr_client_uno = ac.client_uno
where ba.tran_type IN ('RA', 'CR')
group by ba.payr_client_uno
Currently, this query will produce at least 1 row per client with a date, the problem is that there are some clients that will have between 2 and 10 dates associated with them bloating the return table to about 30,000 row instead of an idealistic 246 rows or less.
When i try doing max(tran_uno) to get the most recent transaction number, i get the same result, some have 1 value and others have multiple values.
The bigger picture has 4 other queries being performed doing other parts, i have only included the parts that pertain to the question.
Edit (2011-10-14 # 1:45PM):
select
ba.payr_client_uno as client_uno
, max(ba.row_uno) as row_uno
into #Bills
from blt_bill_amt ba
inner join hbm_matter m on ba.matter_uno = m.matter_uno
inner join hbm_client c on m.client_uno = c.client_uno
inner join hbm_persnl p on c.resp_empl_uno = p.empl_uno
where p.login = #login
and c.status_code = 'C'
and ba.tran_type in ('CR', 'RA')
group by ba.payr_client_uno
order by ba.payr_client_uno
--Obtain list of Transaction Date and Amount for the Transaction
select
b.client_uno
, ba.tran_date
, ba.tc_total_amt
from blt_bill_amt ba
inner join #Bills b on ba.row_uno = b.row_uno
Not quite sure what was going on but seems the Temp Tables were not acting right at all. Ideally i would have 246 rows of data, but with the previous query syntax it would produce from 400-5000 rows of data, obviously duplications on data.
I think you can use ranking to achieve what you want:
WITH ranked AS (
SELECT
client_uno = ba.payr_client_uno,
ba.tran_date,
be.tc_total_amt,
rnk = ROW_NUMBER() OVER (
PARTITION BY ba.payr_client_uno
ORDER BY ba.tran_uno DESC
)
FROM blt_bill_amt ba
INNER JOIN hbm_matter m ON ba.matter_uno = m.matter_uno
INNER JOIN hbm_client c ON m.client_uno = c.client_uno
INNER JOIN hbm_persnl p ON c.resp_empl_uno = p.empl_uno
WHERE p.login = #login
AND c.status_code = 'C'
AND ba.tran_type IN ('CR', 'RA')
)
SELECT
client_uno,
tran_date,
tc_total_amt
FROM ranked
WHERE rnk = 1
ORDER BY client_uno
Useful reading:
Ranking Functions (Transact-SQL)
ROW_NUMBER (Transact-SQL)
WITH common_table_expression (Transact-SQL)
Using Common Table Expressions

Resources