sql >> Database teknologi >  >> RDS >> Database

Optælling af referencer til en post i en tabel via fremmednøgler

Jeg har for nylig haft brug for at løse opgaven til mit eget formål:at beregne antallet af eksterne poster forbundet med en fremmednøgle for hver post i en tabel (File). Opgaven blev løst til den specifikke struktur i File-tabellen, men hvis det er nødvendigt, kan løsningen omarbejdes til en universel.

Jeg vil præcisere, at løsningen blev udviklet til en ulastet database uden millioner af poster og en opdatering hvert minut, så der var ikke meget bekymring for ydeevnen.

Hovedårsagen var, at antallet af eksterne links til File-tabellen kunne ændre sig under udviklingen, og det ville simpelthen være urimeligt konstant at omskrive forespørgslen. Der var planlagt en vis modularitet i systemet, derfor er alle sluttabeller ikke nøjagtigt kendte.

Scriptet til at oprette to etiketter:

CREATE TABLE [dbo].[File](
	[IdFile] [int] IDENTITY(1, 1) NOT NULL,
	[NameFile] [nvarchar](max) NOT NULL,
	[CountUsage] [int] NOT NULL,
	PRIMARY KEY (IdFile)
)

SET identity_insert [dbo].[File] ON;

INSERT INTO [dbo].[File] ([IdFile], [NameFile],[CountUsage])
VALUES (1, 'test1', 0), (2, 'test2', 1000)

SET identity_insert [dbo].[File] OFF;

CREATE TABLE [dbo].[TestForFiles](
	[IdTest] [int] IDENTITY(1, 1) NOT NULL,
	[IdFileForTest] [int] NOT NULL,
	PRIMARY KEY (IdTest)
)

ALTER TABLE [dbo].[TestForFiles]  WITH CHECK ADD  CONSTRAINT [FK_TestForFiles_File] FOREIGN KEY([IdFileForTest])
REFERENCES [dbo].[File] ([IdFile])

ALTER TABLE [dbo].[TestForFiles] CHECK CONSTRAINT [FK_TestForFiles_File]

INSERT INTO [dbo].[TestForFiles] ([IdFileForTest])
VALUES (1), (1), (1), (2)

Vi får tabellerne File og TestForFiles. TestForFiles-tabellen refererer til File-tabellen ved IdFileForTest-feltet.

Vi indhenter følgende datasæt:

Scriptet genererer en forespørgsel til at tælle antallet af poster i tabellen:

DECLARE @sql_tables nvarchar(max) =	null;

SELECT @sql_tables = CASE WHEN @sql_tables IS NULL THEN '' ELSE @sql_tables + CHAR(13) + CHAR(10) + '		UNION ALL' + CHAR(13) + CHAR(10) END + '		SELECT ' + c.name + ' AS IdFile, count(*) AS FileCount FROM ' + t.name + ' GROUP BY ' + c.name
FROM sys.foreign_key_columns AS fk
INNER JOIN sys.tables AS t ON fk.parent_object_id = t.object_id
INNER JOIN sys.columns AS c ON fk.parent_object_id = c.object_id AND fk.parent_column_id = c.column_id
INNER JOIN sys.columns AS c2 ON fk.referenced_object_id = c2.object_id AND fk.referenced_column_id = c2.column_id
WHERE fk.referenced_object_id = (SELECT object_id FROM sys.tables WHERE name = 'File') AND c2.name = 'IdFile';

IF @sql_tables IS NOT NULL
BEGIN
	DECLARE @sql nvarchar(max) =	'UPDATE dbo.[File]' + CHAR(13) + CHAR(10) + 
		'SET CountUsage = t2.FileCount' + CHAR(13) + CHAR(10) + 
		'FROM dbo.[File]' + CHAR(13) + CHAR(10) + 
		'INNER JOIN (' + CHAR(13) + CHAR(10) +
		'	SELECT IdFile, SUM(FileCount) AS FileCount ' + CHAR(13) + CHAR(10) + 
		'	FROM (' + CHAR(13) + CHAR(10) + 
			@sql_tables + CHAR(13) + CHAR(10) + 
		'	) t' + CHAR(13) + CHAR(10) +
		'	GROUP BY IdFile' + CHAR(13) + CHAR(10) +
		') t2 ON t2.IdFile = dbo.[File].IdFile';

	print @sql;
	EXEC sp_executesql @sql;
END;

Følgende forespørgsel genereres:

UPDATE dbo.[File]
SET CountUsage = t2.FileCount
FROM dbo.[File]
INNER JOIN (
	SELECT IdFile, SUM(FileCount) AS FileCount 
	FROM (
		SELECT IdFileForTest AS IdFile, count(*) AS FileCount FROM TestForFiles GROUP BY IdFileForTest
	) t
	GROUP BY IdFile
) t2 ON t2.IdFile = dbo.[File].IdFile

Efter udførelsen har vi sådan tabelindhold:

Endnu en gang blev opgaven løst for en specifik fil-tabel, optælling virker kun for tilfælde, hvor der er fremmednøgler på IdFile-feltet.

Denne artikel er oversat af Codingsightteam med tilladelse fra forfatteren.


  1. Sådan sletter du data fra Elastisearch

  2. Sådan får du årets dag fra en dato i PostgreSQL

  3. Betyder udvikling af kontaktoplysninger at ændre din database?

  4. SSMS version 18 – ingen databasediagrammer