How to formulate T-SQL to exclude duplicates? - tsql

I am trying to develop a query to just return non-duplicate records so that I can add these to my database, but I keep getting the duplicate record error.
I tried your solution but am still getting duplicate error problem. I deleted the 35 rows which were duplicate. What else could be causing this? Here is my query. Part of the confusion I think is that measureid is a single column in j5c_MasterMeasures, but this value comes from two fields in j5c_ListBoxMeasures_Sys.
CREATE TABLE #GOOD_RECORDS3 (STUDENTID VARCHAR(50), MEASUREDATE SMALLDATETIME, MEASUREID VARCHAR(100),
score_10 VARCHAR(100))
INSERT INTO #GOOD_RECORDS3
select A.studentid, A.measuredate, B.measurename+' ' +B.LabelName, A.score_10
from [J5C_Measures_Sys] A join [J5C_ListBoxMeasures_Sys] B on A.MeasureID = B.MeasureID
except
select A.studentid, A.measuredate, B.measurename+' ' +B.LabelName, A.score_10
from [J5C_Measures_Sys] A join [J5C_ListBoxMeasures_Sys] B on A.MeasureID = B.MeasureID
GROUP BY A.studentid, A.measuredate, B.measurename, B.LabelName, A.score_10
having COUNT(A.score_10) > 1
delete #GOOD_RECORDS3
from #GOOD_RECORDS3 a
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u'
join syscolumns sc on so.id = sc.id and sc.name = 'score_10'
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name
WHERE A.SCORE_10 IS NOT NULL AND A.STUDENTID IS NOT NULL AND A.MEASUREID IS NOT NULL
and exists (select 1 from J5C_MasterMeasures M
where M.StudentID = A.StudentID
and M.MeasureID = A.MeasureID)
Insert into J5C_MasterMeasures (studentid, measuredate, measureid, nce)
select A.studentid, A.measuredate, a.MEASUREID, A.score_10
from #GOOD_RECORDS3 a
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u'
join syscolumns sc on so.id = sc.id and sc.name = 'score_10'
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name
WHERE A.SCORE_10 IS NOT NULL AND A.STUDENTID IS NOT NULL AND A.MEASUREID IS NOT NULL

You have not menstioned the specifics of the unique constraint on J5C_MasterMeasures. Therefore, I assumed that all four columns being inserted were part of the constraint. In addition, your use of Except leads me to believe that you are using SQL Server 2005 or later. In addition, it is not clear how the join to J5C_MeasureNamesV2_Sys fits into the design or solution.
With GoodRecords As
(
Select A.StudentId
, A.measuredate
, B.measurename+ ' ' +B.LabelName
, A.score_10 As NCE
From [J5C_Measures_Sys] A
Join [J5C_ListBoxMeasures_Sys] B
On A.MeasureID = B.MeasureID
Where A.StudentId Is Not Null
And A.Score_10 Is Not Null
And A.MeasureId Is Not Null
Group By A.StudentId
, A.MeasureDate
, B.MeasureName+ ' ' +B.LabelName
, A.score_10
Having Count(A.Score_10) = 0
)
Insert J5C_MasterMeasures ( StudentId, MeasureData, MeasureId, NCE )
Select GR.StudentId, GR.MeasureData, GR.MeasureId, GR.NCE
From GoodRecords As GR
Join [J5C_MeasureNamesV2_Sys] v
On v.Score_field_id = 'Score_10'
Where Not Exists (
Select 1
From J5C_MasterMeasures As J1
Where J1.StudentId = GR.StudentId
And J1.MeasureData = GR.MeasureData
And J1.MeasureId = GR.MeasureId
And J1.NCE = GR.NCE
)

Related

SELECT Value even if NULL on LEFT JOIN

I am trying to pull data out and chuck it into a Stimulsoft report. The problem I am having is that I need it to output to two columns. I also need every "manager" record to show even if the count assigned to said record is NULL.
This is what i have at the moment:
DECLARE #ManagerCount INT = (( SELECT Count(*) FROM AM WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0 ) + 1) / 2
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
SELECT * FROM (
SELECT ta.id AS id1, ta.AMName AS ManagerName1, COUNT(*) AS ManagerCount1 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID BETWEEN 1 AND #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.ID, ta.AMName
) a
LEFT JOIN
(
SELECT ta.id AS id2,ta.AMName AS ManagerName2, COUNT(*) AS ManagerCount2 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID > #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.AMName, ta.ID
) b ON a.id1 + #ManagerCount = b.id2
Which ends up returning something like:
There are 18 managers so 9 per column, but this code doesn't show them all since anything that doesn't have a count in the first left join, won't show, and therefore the same row in column 2 doesn't show.
Results of SELECT * FROM #tmp_AM1:
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
SELECT * FROM (
SELECT ta.id AS id1, ta.AMName AS ManagerName1, COUNT(*) AS ManagerCount1 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID BETWEEN 1 AND #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.ID, ta.AMName
) a
LEFT OUTER JOIN
(
SELECT ta.id AS id2,ta.AMName AS ManagerName2, COUNT(*) AS ManagerCount2 FROM #tmp_AM1 tA INNER JOIN Job J ON tA.AMID = j.AMID
WHERE ta.ID > #ManagerCount AND j.jobStatusID != 5
GROUP BY ta.AMName, ta.ID
) b ON a.id1 + #ManagerCount = b.id2 where ManagerName2 IS Null and ManagerCount2 IS NULL
just you want to use LEFT OUTER JOIN for select row even there is have any null values.,
Since the two subqueries are pretty much identical, except the where-statement, I would consiter rewriting it into one single query. I'm not sure why you need the same columns outputed into different columns in the result, but something like this might work:
WITH cte AS (
SELECT
ta.id AS id
,ta.AMName AS ManagerName
,COUNT(*) AS ManagerCount
,CASE WHEN ta.ID BETWEEN 1 AND #ManagerCount THEN 0 ELSE 1 END AS something
FROM
#tmp_AM1 tA
INNER JOIN Job J ON tA.AMID = j.AMID
WHERE
j.jobStatusID != 5
GROUP BY
ta.ID
,ta.AMName
,CASE WHEN ta.ID BETWEEN 1 AND #ManagerCount THEN 0 ELSE 1 END
)
SELECT
CASE WHEN something = 0 THEN cte.id ELSE null END AS id1
,CASE WHEN something = 0 THEN cte.ManagerName ELSE null END AS ManagerName1
,CASE WHEN something = 0 THEN cte.ManagerCount ELSE null END AS ManagerCount1
,CASE WHEN something = 1 THEN cte.id ELSE null END AS id2
,CASE WHEN something = 1 THEN cte.ManagerName ELSE null END AS ManagerName2
,CASE WHEN something = 1 THEN cte.ManagerCount ELSE null END AS ManagerCount2
FROM
cte
Probably not the best approach but i got the correct output using:
DECLARE #ManagerCount INT = (( SELECT Count(*) FROM AM WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0 ) + 1) / 2
DECLARE #tmp_AM1 TABLE (AMID INT, AMName NVARCHAR(100), ID INT)
INSERT INTO #tmp_AM1 SELECT AMID, AMName, row_number() over (order by AMID ) FROM AM
WHERE dbo.AM.AMCurrent = 1 AND dbo.AM.OmitInReport = 0
ORDER By AMName
SELECT ManagerName1, ManagerName2, ManagerCount1, ManagerCount2 FROM (
SELECT AMID, ta.id AS id1, ta.AMName AS ManagerName1 FROM #tmp_AM1 tA
WHERE (ta.ID BETWEEN 1 AND #ManagerCount)
) a
LEFT JOIN
(
SELECT AMID, ISNULL(COUNT(*), 0) AS ManagerCount1 FROM Job j
INNER JOIN tblJobOutcome jO ON j.JobOutcomeID = jo.JobOutcomeID AND jO.JobOutcomeID != 5
GROUP BY AMID
) a1 ON a.AMID = a1.AMID
LEFT JOIN
(
SELECT AMID, ta.id AS id2, ta.AMName AS ManagerName2 FROM #tmp_AM1 tA
WHERE (ta.ID > #ManagerCount)
) b ON a.id1 + #ManagerCount = b.id2
LEFT JOIN
(
SELECT AMID, ISNULL(COUNT(*), 0) AS ManagerCount2 FROM Job j
INNER JOIN tblJobOutcome jO ON j.JobOutcomeID = jo.JobOutcomeID AND jO.JobOutcomeID != 5
GROUP BY AMID
) b1 ON b.AMID = b1.AMID
Gives me the correct output in two columns.
gives me this:

How to write valid If clause inside select or write function

I have procedure like this and I get error in If clause. I think it is because COUNT. But my clause have to be like that so I don't know how to solve it. Maybe it would be good to create a function or something similar. Rest of the code is okay
CREATE PROCEDURE DohvatiSveUgovore #zavodId int
AS
BEGIN
DECLARE #TempUgovori TABLE
(
Id int,
UstrojstvenaJedinica nvarchar(100),
VrstaUgovora nvarchar(100),
KlasaUgovora nvarchar(100),
UrudzbeniBrojUgovora nvarchar(100),
DatumPocetkaUgovora nvarchar(10),
DatumIstekaUgovora nvarchar(10)
)
INSERT INTO #TempUgovori(Id, UstrojstvenaJedinica, VrstaUgovora, KlasaUgovora, UrudzbeniBrojUgovora, DatumPocetkaUgovora, DatumIstekaUgovora)
SELECT
u.Id,
ISNULL(STRING_AGG(LTRIM(RTRIM(z.SkraceniNaziv)), ', '), '') AS 'UstrojstvenaJedinica',
vu.Naziv AS 'VrstaUgovora',
ISNULL(u.KlasaUgovora, '') AS 'KlasaUgovora',
ISNULL(u.UrudzbeniBrojUgovora, '') AS 'UrudzbeniBrojUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumPocetkaUgovora, 104), '')) AS 'DatumPocetkaUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumIstekaUgovora, 104), '')) AS 'DatumIstekaUgovora'
FROM Ugovor AS u
LEFT JOIN VezaUgovorUstrojstvenaJedinica AS vuu
ON u.Id = vuu.UgovorId
INNER JOIN SifVrstaUgovora AS vu
ON u.VrstaUgovoraId = vu.Id
LEFT JOIN [TEST_MaticniPodaci2].hcphs.SifZavod AS z
ON vuu.UstrojstvenaJedinicaId = z.Id
if( (SELECT COUNT(UstrojstvenaJedinicaId) FROM VezaUgovorUstrojstvenaJedinica WHERE UstrojstvenaJedinicaId = 'HCPHS') = 1)
begin
(SELECT * FROM VezaUgovorUstrojstvenaJedinica WHERE UstrojstvenaJedinicaId = 'HCPHS')
end
ELSE
(SELECT * FROM VezaUgovorUstrojstvenaJedinica WHERE Isdeleted = 0 and UstrojstvenaJedinicaId = #zavodId)
end
ERROR is here in Group by and I don't know why.
GROUP BY u.Id, vu.Naziv, u.KlasaUgovora, u.UrudzbeniBrojUgovora, u.DatumPocetkaUgovora, u.DatumIstekaUgovora
SELECT
tu.Id,
tu.UstrojstvenaJedinica AS 'UstrojstvenaJedinica',
tu.VrstaUgovora AS 'VrstaUgovora',
tu.KlasaUgovora AS 'KlasaUgovora',
tu.UrudzbeniBrojUgovora AS 'UrudzbeniBrojUgovora',
tu.DatumIstekaUgovora AS 'DatumPocetkaUgovora',
tu.DatumIstekaUgovora AS 'DatumIstekaUgovora',
ISNULL(STRING_AGG(LTRIM(RTRIM(p.Naziv)), ', '), '') as 'Partner'
FROM #TempUgovori AS tu
LEFT JOIN VezaUgovorPartner AS vup
on tu.Id = vup.UgovorId
LEFT JOIN [TEST_MaticniPodaci2].dbo.Partner as p
ON vup.PartnerId = p.PartnerID
GROUP BY tu.Id, tu.UstrojstvenaJedinica, tu.VrstaUgovora, tu.KlasaUgovora, tu.UrudzbeniBrojUgovora, tu.DatumPocetkaUgovora, tu.DatumIstekaUgovora
END
EXEC [TEST_Ugovori_Prod].[dbo].[DohvatiSve] 6;
GO
I am sorry for too much code but without it I can't run query.
It looks like you're trying to tell SQL Server to join to VezaUgovorUstrojstvenaJedinica differently depending on the circumstances. The sql engine can't figure that out. For a very brief discussion on how sql evaluates a query, here's a start:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/70efeffe-76b9-4b7e-b4a1-ba53f5d21916/order-of-execution-of-sql-queries?forum=transactsql
Maybe something like this will work for you?
CREATE PROCEDURE DohvatiSveUgovore #zavodId int
AS
BEGIN
DECLARE #TempUgovori TABLE
(
Id int,
UstrojstvenaJedinica nvarchar(100),
VrstaUgovora nvarchar(100),
KlasaUgovora nvarchar(100),
UrudzbeniBrojUgovora nvarchar(100),
DatumPocetkaUgovora nvarchar(10),
DatumIstekaUgovora nvarchar(10)
);
DECLARE #HCPHS integer;
SELECT
#HCPHS = COUNT(UstrojstvenaJedinicaId)
FROM
VezaUgovorUstrojstvenaJedinica
WHERE
UstrojstvenaJedinicaId = 'HCPHS';
IF #HCPHS = 1
INSERT INTO #TempUgovori(Id, UstrojstvenaJedinica, VrstaUgovora, KlasaUgovora, UrudzbeniBrojUgovora, DatumPocetkaUgovora, DatumIstekaUgovora)
SELECT
u.Id,
ISNULL(STRING_AGG(LTRIM(RTRIM(z.SkraceniNaziv)), ', '), '') AS 'UstrojstvenaJedinica',
vu.Naziv AS 'VrstaUgovora',
ISNULL(u.KlasaUgovora, '') AS 'KlasaUgovora',
ISNULL(u.UrudzbeniBrojUgovora, '') AS 'UrudzbeniBrojUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumPocetkaUgovora, 104), '')) AS 'DatumPocetkaUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumIstekaUgovora, 104), '')) AS 'DatumIstekaUgovora'
FROM Ugovor AS u
LEFT JOIN VezaUgovorUstrojstvenaJedinica AS vuu
ON u.Id = vuu.UgovorId
INNER JOIN SifVrstaUgovora AS vu
ON u.VrstaUgovoraId = vu.Id
LEFT JOIN [TEST_MaticniPodaci2].hcphs.SifZavod AS z
ON vuu.UstrojstvenaJedinicaId = z.Id
<JOIN OF SOME KIND>
(SELECT * FROM VezaUgovorUstrojstvenaJedinica WHERE UstrojstvenaJedinicaId = 'HCPHS')
ON <SOME CRITERIA>
GROUP BY u.Id, vu.Naziv, u.KlasaUgovora, u.UrudzbeniBrojUgovora, u.DatumPocetkaUgovora, u.DatumIstekaUgovora
ELSE
INSERT INTO #TempUgovori(Id, UstrojstvenaJedinica, VrstaUgovora, KlasaUgovora, UrudzbeniBrojUgovora, DatumPocetkaUgovora, DatumIstekaUgovora)
SELECT
u.Id,
ISNULL(STRING_AGG(LTRIM(RTRIM(z.SkraceniNaziv)), ', '), '') AS 'UstrojstvenaJedinica',
vu.Naziv AS 'VrstaUgovora',
ISNULL(u.KlasaUgovora, '') AS 'KlasaUgovora',
ISNULL(u.UrudzbeniBrojUgovora, '') AS 'UrudzbeniBrojUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumPocetkaUgovora, 104), '')) AS 'DatumPocetkaUgovora',
(SELECT ISNULL(convert(varchar(10), u.DatumIstekaUgovora, 104), '')) AS 'DatumIstekaUgovora'
FROM Ugovor AS u
LEFT JOIN VezaUgovorUstrojstvenaJedinica AS vuu
ON u.Id = vuu.UgovorId
INNER JOIN SifVrstaUgovora AS vu
ON u.VrstaUgovoraId = vu.Id
LEFT JOIN [TEST_MaticniPodaci2].hcphs.SifZavod AS z
ON vuu.UstrojstvenaJedinicaId = z.Id
<JOIN OF SOME KIND>
(SELECT * FROM VezaUgovorUstrojstvenaJedinica WHERE Isdeleted = 0 and UstrojstvenaJedinicaId = #zavodId)
ON <SOME CRITERIA>
GROUP BY u.Id, vu.Naziv, u.KlasaUgovora, u.UrudzbeniBrojUgovora, u.DatumPocetkaUgovora, u.DatumIstekaUgovora

Find dependent objects for a table or view

Background
When dropping (or replacing) objects in PostgreSQL, if there are dependencies, the drop will fail (without specifying CASCADE).
Problem
The error message returned by the database does not list the dependent objects.
Example Solution
The query might look something like:
SELECT * FROM information_schema i, pg_depend pd WHERE
i.object_id = pd.object_id AND
i.object_type = 'TABLE' AND
i.object_schema = 'public' AND
i.object_name = 'table_with_dependents';
The objid is missing.
Related
http://postgresql.1045698.n5.nabble.com/information-schema-problem-td2144069.html
http://www.alberton.info/postgresql_meta_info.html
Question
How do you generate a list of dependent objects by name and type?
The suggested solution didn't work for me with postgresql 9.1.4
this worked:
SELECT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
, pg_attribute.attname as column_name
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
AND pg_depend.refobjsubid = pg_attribute.attnum
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE
source_ns.nspname = 'my_schema'
AND source_table.relname = 'my_table'
AND pg_attribute.attnum > 0
AND pg_attribute.attname = 'my_column'
ORDER BY 1,2;
The easy way is:
BEGIN;
DROP TABLE tablename CASCADE;
DROP VIEW viewname CASCADE;
ROLLBACK;
For PostgreSQL 9.3 onward use the following view and functions to show any user object dependency. I also updated https://wiki.postgresql.org/wiki/Pg_depend_display.
/**** Usage Examples ****
-- Examine the entire object hierarchy
SELECT report.dependency_tree('');
-- Dependencies for any relations with names containing match (in regular expression)
SELECT report.dependency_tree('match');
-- Dependencies for relations person & address
SELECT report.dependency_tree('{person,address}'::text[]);
-- Dependencies for function slice
SELECT report.dependency_tree(ARRAY['slice'::regproc]);
-- Dependencies for type hstore
SELECT report.dependency_tree(ARRAY['hstore'::regtype]);
-- Dependencies for triggers by the name updated
SELECT report.dependency_tree(ARRAY(
SELECT oid FROM pg_trigger WHERE tgname ~ 'updated'
));
-- Dependencies for foreign key constraint names starting with product
SELECT report.dependency_tree(ARRAY(
SELECT oid FROM pg_constraint
WHERE conname ~ '^product.*_fk'
));
*/
DROP VIEW IF EXISTS report.dependency;
CREATE OR REPLACE VIEW report.dependency AS
WITH RECURSIVE preference AS (
SELECT 10 AS max_depth
, 16384 AS min_oid -- user objects only
, '^(londiste|pgq|pg_toast)'::text AS schema_exclusion
, '^pg_(conversion|language|ts_(dict|template))'::text AS class_exclusion
, '{"SCHEMA":"00", "TABLE":"01", "TABLE CONSTRAINT":"02", "DEFAULT VALUE":"03",
"INDEX":"05", "SEQUENCE":"06", "TRIGGER":"07", "FUNCTION":"08",
"VIEW":"10", "MATERIALIZED VIEW":"11", "FOREIGN TABLE":"12"}'::json AS type_sort_orders
)
, dependency_pair AS (
SELECT objid
, array_agg(objsubid ORDER BY objsubid) AS objsubids
, upper(obj.type) AS object_type
, coalesce(obj.schema, substring(obj.identity, E'(\\w+?)\\.'), '') AS object_schema
, obj.name AS object_name
, obj.identity AS object_identity
, refobjid
, array_agg(refobjsubid ORDER BY refobjsubid) AS refobjsubids
, upper(refobj.type) AS refobj_type
, coalesce(CASE WHEN refobj.type='schema' THEN refobj.identity
ELSE refobj.schema END
, substring(refobj.identity, E'(\\w+?)\\.'), '') AS refobj_schema
, refobj.name AS refobj_name
, refobj.identity AS refobj_identity
, CASE deptype
WHEN 'n' THEN 'normal'
WHEN 'a' THEN 'automatic'
WHEN 'i' THEN 'internal'
WHEN 'e' THEN 'extension'
WHEN 'p' THEN 'pinned'
END AS dependency_type
FROM pg_depend dep
, LATERAL pg_identify_object(classid, objid, 0) AS obj
, LATERAL pg_identify_object(refclassid, refobjid, 0) AS refobj
, preference
WHERE deptype = ANY('{n,a}')
AND objid >= preference.min_oid
AND (refobjid >= preference.min_oid OR refobjid = 2200) -- need public schema as root node
AND coalesce(obj.schema, substring(obj.identity, E'(\\w+?)\\.'), '') !~ preference.schema_exclusion
AND coalesce(CASE WHEN refobj.type='schema' THEN refobj.identity
ELSE refobj.schema END
, substring(refobj.identity, E'(\\w+?)\\.'), '') !~ preference.schema_exclusion
GROUP BY objid, obj.type, obj.schema, obj.name, obj.identity
, refobjid, refobj.type, refobj.schema, refobj.name, refobj.identity, deptype
)
, dependency_hierarchy AS (
SELECT DISTINCT
0 AS level,
refobjid AS objid,
refobj_type AS object_type,
refobj_identity AS object_identity,
--refobjsubids AS objsubids,
NULL::text AS dependency_type,
ARRAY[refobjid] AS dependency_chain,
ARRAY[concat(preference.type_sort_orders->>refobj_type,refobj_type,':',refobj_identity)] AS dependency_sort_chain
FROM dependency_pair root
, preference
WHERE NOT EXISTS
(SELECT 'x' FROM dependency_pair branch WHERE branch.objid = root.refobjid)
AND refobj_schema !~ preference.schema_exclusion
UNION ALL
SELECT
level + 1 AS level,
child.objid,
child.object_type,
child.object_identity,
--child.objsubids,
child.dependency_type,
parent.dependency_chain || child.objid,
parent.dependency_sort_chain || concat(preference.type_sort_orders->>child.object_type,child.object_type,':',child.object_identity)
FROM dependency_pair child
JOIN dependency_hierarchy parent ON (parent.objid = child.refobjid)
, preference
WHERE level < preference.max_depth
AND child.object_schema !~ preference.schema_exclusion
AND child.refobj_schema !~ preference.schema_exclusion
AND NOT (child.objid = ANY(parent.dependency_chain)) -- prevent circular referencing
)
SELECT * FROM dependency_hierarchy
ORDER BY dependency_chain ;
-- Procedure to report depedency tree using regexp search pattern (relation-only)
CREATE OR REPLACE FUNCTION report.dependency_tree(search_pattern text)
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
WHERE object_identity ~ search_pattern
)
, list AS (
SELECT
format('%*s%s %s', -4*level
, CASE WHEN object_identity ~ search_pattern THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
WHERE length(search_pattern) > 0
-- Do NOT waste search time on blank/null search_pattern.
UNION
-- Query the entire dependencies instead.
SELECT
format('%*s%s %s', 4*level, '', object_type, object_identity) AS depedency_tree
, dependency_sort_chain
FROM report.dependency
WHERE length(coalesce(search_pattern,'')) = 0
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
-- Procedure to report depedency tree by specific relation name(s) (in text array)
CREATE OR REPLACE FUNCTION report.dependency_tree(object_names text[])
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
JOIN unnest(object_names) AS target(objname) ON objid = objname::regclass
)
, list AS (
SELECT DISTINCT
format('%*s%s %s', -4*level
, CASE WHEN object_identity = ANY(object_names) THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
-- Procedure to report depedency tree by oid
CREATE OR REPLACE FUNCTION report.dependency_tree(object_ids oid[])
RETURNS TABLE(dependency_tree text)
SECURITY DEFINER LANGUAGE SQL
AS $function$
WITH target AS (
SELECT objid, dependency_chain
FROM report.dependency
JOIN unnest(object_ids) AS target(objid) USING (objid)
)
, list AS (
SELECT DISTINCT
format('%*s%s %s', -4*level
, CASE WHEN report.objid = ANY(object_ids) THEN '*' END
, object_type, object_identity
) AS dependency_tree
, dependency_sort_chain
FROM target
JOIN report.dependency report
ON report.objid = ANY(target.dependency_chain) -- root-bound chain
OR target.objid = ANY(report.dependency_chain) -- leaf-bound chain
)
SELECT dependency_tree FROM list
ORDER BY dependency_sort_chain;
$function$ ;
Include nested views in the query as follows:
WITH RECURSIVE view_deps AS (
SELECT DISTINCT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
WHERE NOT (dependent_ns.nspname = source_ns.nspname AND dependent_view.relname = source_table.relname)
UNION
SELECT DISTINCT dependent_ns.nspname as dependent_schema
, dependent_view.relname as dependent_view
, source_ns.nspname as source_schema
, source_table.relname as source_table
FROM pg_depend
JOIN pg_rewrite ON pg_depend.objid = pg_rewrite.oid
JOIN pg_class as dependent_view ON pg_rewrite.ev_class = dependent_view.oid
JOIN pg_class as source_table ON pg_depend.refobjid = source_table.oid
JOIN pg_namespace dependent_ns ON dependent_ns.oid = dependent_view.relnamespace
JOIN pg_namespace source_ns ON source_ns.oid = source_table.relnamespace
INNER JOIN view_deps vd
ON vd.dependent_schema = source_ns.nspname
AND vd.dependent_view = source_table.relname
AND NOT (dependent_ns.nspname = vd.dependent_schema AND dependent_view.relname = vd.dependent_view)
)
SELECT *
FROM view_deps
ORDER BY source_schema, source_table;
If you care about specific table attributes add this to the top portion of the recursive CTE:
JOIN pg_attribute ON pg_depend.refobjid = pg_attribute.attrelid
AND pg_depend.refobjsubid = pg_attribute.attnum
...
WHERE
source_ns.nspname = 'my_schema'
AND source_table.relname = 'my_table'
AND pg_attribute.attnum > 0
AND pg_attribute.attname = 'my_column'
pg_constraint contains all constrains in the database you can list the oid of dependent tables using confrelid and conrelid from all all the foreign key constraints
query looks like this
select confrelid,conrelid from pg_constraint where contype='f';

Syntax for SQL Not In List?

I am trying to develop a T-SQL query to exclude all rows from another table "B". This other table "B" has 3 columns comprising its PK for a total of 136 rows. So I want to select all columns from table "A" minus those from table "B". How do I do this? I don't think this query is correct because I am still getting a duplicate record error:
CREATE TABLE #B (STUDENTID VARCHAR(50), MEASUREDATE SMALLDATETIME, MEASUREID VARCHAR(50))
INSERT #B
SELECT studentid, measuredate, measureid
from [J5C_Measures_Sys]
GROUP BY studentid, measuredate, measureid
HAVING COUNT(*) > 1
insert into J5C_MasterMeasures (studentid, measuredate, measureid, rit)
select A.studentid, A.measuredate, B.measurename+' ' +B.LabelName, A.score_14
from [J5C_Measures_Sys] A
join [J5C_ListBoxMeasures_Sys] B on A.MeasureID = B.MeasureID
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u'
join syscolumns sc on so.id = sc.id and sc.name = 'score_14'
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name
where a.score_14 is not null AND B.MEASURENAME IS NOT NULL
and (A.studentid NOT IN (SELECT studentid from #B)
and a.measuredate NOT IN (SELECT measuredate from #B)
and a.measureid NOT IN (SELECT measureid from #B))
use NOT EXISTS...NOT IN doesn't filter out NULLS
insert into J5C_MasterMeasures (studentid, measuredate, measureid, rit)
select A.studentid, A.measuredate, B.measurename+' ' +B.LabelName, A.score_14
from [J5C_Measures_Sys] A
join [J5C_ListBoxMeasures_Sys] B on A.MeasureID = B.MeasureID
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u'
join syscolumns sc on so.id = sc.id and sc.name = 'score_14'
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name
where a.score_14 is not null AND B.MEASURENAME IS NOT NULL
AND NOT EXISTS (select 1 from #B where #b.studentid = A.studentid
and a.measuredate = #B.measuredate
and a.measureid = #B.measureid)
and not exists (select 1 from J5C_MasterMeasures z
where z.studentid = A.studentid)
Just so you know, take a look at Select all rows from one table that don't exist in another table
Basically there are at least 5 ways to select all rows from onr table that are not in another table
NOT IN
NOT EXISTS
LEFT and RIGHT JOIN
OUTER APLY (2005+)
EXCEPT (2005+)
Here is a general solution for the difference operation using left join:
select * from FirstTable
left join SecondTable on FirstTable.ID = SecondTable.ID
where SecondTable.ID is null
Of course yours would have a more complicated join on clause, but the basic operation is the same.
I think you can use "NOT IN" with a subquery, but you say you have a multi-field key?
I'd be thinking about using a left outer join and then testing for null on the right...
Martin.

How to use ROW_NUMBER in the following procedure?

I have the following stored procedure which returns A, B, and the count in descending order. I am trying to use ROW_NUMBER, so I can page the records, but I want the first row number 1 to be the record with the highest count, so basically, if I return a table with 3 records and the count is 30, 20, 10, then row number 1 should correspond with count 30, row number 2 should correspond with count 20, and row number 3 should correspond with count 10. dbo.f_GetCount is a function that returns a count.
create procedure dbo.Test
as
#A nvarchar(300) = NULL,
#B nvarchar(10) = NULL
as
select #A = nullif(#A,'')
,#B = nullif(#B,'');
select h.A
,hrl.B
,dbo.f_GetCount(hrl.A,h.B) as cnt
from dbo.hrl
inner join dbo.h
on h.C = hrl.C
where(#A is null
or h.A like '%'+#A+'%'
)
and (#B is null
or hrl.B = #B
)
group by hrl.B
,h.A
order by cnt desc;
WITH q AS
(
SELECT h.A, hrl.B,
dbo.f_GetCount(hrl.A,h.B) as cnt
FROM dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE (#A IS NULL OR h.A like '%' + #A + '%')
AND (#B IS NULL OR hrl.B = #B)
GROUP BY hrl.B, h.A
)
SELECT q.*, ROW_NUMBER() OVER (ORDER BY cnt DESC) AS rn
FROM q
ORDER BY rn DESC
To retrieve first 10 rows, use:
WITH q AS
(
SELECT h.A, hrl.B,
dbo.f_GetCount(hrl.A,h.B) as cnt
FROM dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE (#A IS NULL OR h.A like '%' + #A + '%')
AND (#B IS NULL OR hrl.B = #B)
GROUP BY hrl.B, h.A
)
SELECT TOP 10 q.*,
ROW_NUMBER() OVER (ORDER BY cnt DESC, A, B) AS rn
FROM q
ORDER BY cnt DESC, A, B
To retrieve rows between 11 and 20, use:
SELECT *
FROM (
WITH q AS
(
SELECT h.A, hrl.B,
dbo.f_GetCount(hrl.A,h.B) as cnt
FROM dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE (#A IS NULL OR h.A like '%' + #A + '%')
AND (#B IS NULL OR hrl.B = #B)
GROUP BY hrl.B, h.A
)
SELECT q.*,
ROW_NUMBER() OVER (ORDER BY cnt DESC, A, B) AS rn
FROM q
) qq
WHERE rn BETWEEN 11 AND 20
ORDER BY cnt DESC, A, B
I would use a sub-query to get the values of the function into the result, and then the ROW_NUMBER ranking function, like so:
select
ROW_NUMBER() over (order by t.cnt desc) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(#A IS NULL OR h.A like '%' + #A + '%') AND
(#B IS NULL OR hrl.B = #B)
GROUP BY
hrl.B, h.A
) as t
order by
1
If you wanted only a certain section of results (say, for paging), then you would need another subquery, and then filter on the row number:
select
t.*
from
(
select
ROW_NUMBER() over (order by t.cnt desc) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(#A IS NULL OR h.A like '%' + #A + '%') AND
(#B IS NULL OR hrl.B = #B)
GROUP BY
hrl.B, h.A
) as t
) as t
where
t.RowId between 1 and 10
order by
t.RowId
Note that in this query, you could put ROW_NUMBER anywhere in the select list, since you are no longer reliant on using the "order by 1" syntax for the order by statement.
There is a subtle issue here when calling this query multiple times. It is not guaranteed that the order in which the records are returned are going to be consistent if the number of items in each group is not unique. In order to address this, you have to change the ROW_NUMBER function to order on the fields that make up the group in the count.
In this case, it would be A and B, resulting in:
select
t.*
from
(
select
ROW_NUMBER() over (order by t.cnt desc, t.A, t.B) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(#A IS NULL OR h.A like '%' + #A + '%') AND
(#B IS NULL OR hrl.B = #B)
GROUP BY
hrl.B, h.A
) as t
) as t
where
t.RowId between 1 and 10
order by
t.RowId
This ends up ordering the results consistently between calls when the count of the items between groups is not unique (assuming the same set of data).
SELECT h.A, hrl.B,
dbo.f_GetCount(hrl.A,h.B) as cnt,
ROW_NUMBER() over (order by cnt desc) as row_num
FROM dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE (#A IS NULL OR h.A like '%' + #A + '%')
AND (#B IS NULL OR hrl.B = #B)
GROUP BY hrl.B, h.A
ORDER BY cnt desc
This should do the trick. I don't have SSMS in front of me to test, but you MAY have to substitute the usage of 'cnt' in the ROW_NUMBER's order by clause with a second call to the function, but this should give you the general idea.