sql >> Databasteknik >  >> RDS >> Database

Räkna referenser till en post i en tabell via främmande nycklar

Jag har nyligen behövt lösa uppgiften för mitt eget syfte:att beräkna antalet externa poster länkade med en främmande nyckel för varje post i en tabell (File). Uppgiften löstes för den specifika strukturen i File-tabellen, men vid behov kan lösningen omarbetas till en universell.

Jag ska förtydliga att lösningen utvecklades för en olastad databas, utan miljontals poster och en uppdatering varje minut, så det var inte mycket oro över prestandan.

Den huvudsakliga anledningen var att antalet externa länkar till filtabellen kunde ändras under utvecklingen och det skulle helt enkelt vara orimligt att ständigt skriva om frågan. En viss modularitet planerades i systemet, därför är alla sluttabeller inte exakt kända.

Skript för att skapa två 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 tabellerna File och TestForFiles. Tabellen TestForFiles hänvisar till filtabellen med fältet IdFileForTest.

Vi får följande datauppsättning:

Skriptet genererar en fråga för att räkna antalet 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öljande fråga genereras:

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 körningen har vi sådant tabellinnehåll:

Än en gång löstes uppgiften för en specifik filtabell, räkning fungerar endast för fall då det finns främmande nycklar i IdFile-fältet.

Denna artikel har översatts av Codingsightteam med författarens tillstånd.


  1. Vårdata @CreatedDate-kommentaren fungerar inte för mig

  2. Hur man får PostgreSQL på en VPS / dedikerad server

  3. Hur man konfigurerar PostgreSQL för att acceptera alla inkommande anslutningar

  4. Mysql infoga slumpmässig datumtid i ett givet datumintervall