Database
 sql >> Baza danych >  >> RDS >> Database

Zliczanie odwołań do rekordu w tabeli za pomocą kluczy obcych

Niedawno musiałem rozwiązać zadanie do własnego celu:obliczenia liczby rekordów zewnętrznych połączonych kluczem obcym dla każdego rekordu w tabeli (Plik). Zadanie zostało rozwiązane dla określonej struktury tabeli plików, ale w razie potrzeby rozwiązanie można przerobić na uniwersalne.

Wyjaśnię, że rozwiązanie zostało opracowane dla nieobciążonej bazy danych, bez milionów rekordów i aktualizacji co minutę, więc nie było zbytniej obaw o wydajność.

Głównym powodem było to, że liczba zewnętrznych linków do tabeli plików może się zmieniać podczas opracowywania, a ciągłe przepisywanie zapytania byłoby po prostu nierozsądne. W systemie zaplanowano pewną modułowość, dlatego nie wszystkie stoły finałowe są dokładnie znane.

Skrypt do tworzenia dwóch etykiet:

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)

Otrzymujemy tabele File i TestForFiles. Tabela TestForFiles odnosi się do tabeli plików w polu IdFileForTest.

Otrzymujemy następujący zestaw danych:

Skrypt generuje zapytanie w celu zliczenia liczby rekordów w tabeli:

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;

Generowane jest następujące zapytanie:

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

Po wykonaniu mamy taką zawartość tabeli:

Po raz kolejny zadanie zostało rozwiązane dla określonej tabeli plików, liczenie działa tylko w przypadkach, gdy w polu IdFile znajdują się klucze obce.

Ten artykuł został przetłumaczony przez Zespół Codingsight za zgodą autora.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Naucz się podstawowej analizy danych za pomocą funkcji okna SQL

  2. Zrozumienie transakcji w SQL

  3. Zmienna środowiskowa LD_DEBUG

  4. Jak zresetować hasło użytkownika głównego Amazon RDS

  5. Jak zainstalować Libreoffice na Ubuntu 16.04