/*
Test index / fk retrieval query

02.11.2022, TSC
*/
USE [sandbox];

IF OBJECT_ID('dbo.parent') IS NULL
BEGIN
    --DROP TABLE dbo.parent
    ALTER TABLE [dbo].[child]
    DROP CONSTRAINT IF EXISTS [fk_child__REF__parent];
    CREATE TABLE [dbo].[parent] ([id] INT NOT NULL
                                     CONSTRAINT [pk_parent]
                                     PRIMARY KEY ([id]));
    PRINT 'parent table created';
END;

IF OBJECT_ID('dbo.child') IS NULL
BEGIN
    --DROP TABLE dbo.child;
    CREATE TABLE [dbo].[child] ([id] INT IDENTITY NOT NULL,
                                [parent_id] INT NOT NULL,
                                [ins_date] SMALLDATETIME NOT NULL
                                    CONSTRAINT [df_child_COL_insDate]
                                        DEFAULT CURRENT_TIMESTAMP
                                    CONSTRAINT [pk_child]
                                    PRIMARY KEY ([id]));
    PRINT 'child table created';
END;

IF OBJECT_ID('fk_child__REF__parent') IS NULL
BEGIN
    ALTER TABLE [dbo].[child]
    ADD CONSTRAINT [fk_child__REF__parent]
        FOREIGN KEY ([parent_id])
        REFERENCES [dbo].[parent] ([id]);
    PRINT 'fk created';
END;

IF INDEXPROPERTY(OBJECT_ID('child'), 'CIX_child_parent_id', 'IndexID') IS NULL
BEGIN;
    CREATE NONCLUSTERED INDEX [CIX_child_parent_id]
    ON [dbo].[child] ([parent_id]);
    PRINT 'idx created';
END;

TRUNCATE TABLE [dbo].[child];
DELETE FROM [dbo].[parent]
 WHERE 1 = 1;

INSERT INTO [dbo].[parent] ([id])
VALUES (1);

INSERT INTO [dbo].[child] ([parent_id])
VALUES (1);



SELECT            SCHEMA_NAME([tab].[schema_id]) + '.' + [tab].[name] AS [table],
                  [col].[column_id],
                  [col].[name] AS [column_name],
                  CASE
                       WHEN [fk].[object_id] IS NOT NULL THEN '>-'
                       ELSE NULL END AS [rel],
                  SCHEMA_NAME([pk_tab].[schema_id]) + '.' + [pk_tab].[name] AS [primary_table],
                  [pk_col].[name] AS [pk_column_name],
                  [fk_cols].[constraint_column_id] AS [NO],
                  [fk].[name] AS [fk_constraint_name]
  FROM            [sys].[tables] [tab]
 INNER JOIN       [sys].[columns] [col]
    ON [col].[object_id]            = [tab].[object_id]
  LEFT OUTER JOIN [sys].[foreign_key_columns] [fk_cols]
    ON [fk_cols].[parent_object_id] = [tab].[object_id]
   AND [fk_cols].[parent_column_id] = [col].[column_id]
  LEFT OUTER JOIN [sys].[foreign_keys] [fk]
    ON [fk].[object_id]             = [fk_cols].[constraint_object_id]
  LEFT OUTER JOIN [sys].[tables] [pk_tab]
    ON [pk_tab].[object_id]         = [fk_cols].[referenced_object_id]
  LEFT OUTER JOIN [sys].[columns] [pk_col]
    ON [pk_col].[column_id]         = [fk_cols].[referenced_column_id]
   AND [pk_col].[object_id]         = [fk_cols].[referenced_object_id]
 WHERE            [fk].[object_id] IS NOT NULL
 --AND SCHEMA_NAME(tab.SCHEMA_ID) = 'dbo'
 --AND tab.name='customer'
 ORDER BY SCHEMA_NAME([tab].[schema_id]) + '.' + [tab].[name],
          [col].[column_id];


;WITH [ColInfo]
   AS (SELECT      [o].[name] AS [TblName],
                   [s].[name] + '.' + [o].[name] AS [SchemaTbl],
                   [i].[name] AS [IndexName],
                   [i].[is_primary_key] AS [IsPrimaryKey],
                   [i].[is_unique_constraint] AS [IsUniqueConstraint],
                   [i].[is_unique] AS [IsUnique],
                   [c].[name] AS [ColName],
                   [c].[is_computed] AS [IsComputedCol],
                   [ic].[is_included_column] AS [IsIncludedCol],
                   [ic].[key_ordinal],
                   [i].[filter_definition] AS [FilterDefinition]
         FROM      [sys].[objects] [o]
        INNER JOIN [sys].[schemas] [s]
           ON [o].[schema_id] = [s].[schema_id]
        INNER JOIN [sys].[columns] [c]
           ON [o].[object_id] = [c].[object_id]
        INNER JOIN [sys].[indexes] [i]
           ON [c].[object_id] = [i].[object_id]
        INNER JOIN [sys].[index_columns] [ic]
           ON [i].[index_id]  = [ic].[index_id]
          AND [o].[object_id] = [ic].[object_id]
          AND [c].[column_id] = [ic].[column_id])


--- Index Read/Write stats (all tables in current DB) ordered by Reads  (Query 62) (Overall Index Usage - Reads)
SELECT            [o].[name] AS [tblName],
                  [o].[type],
                  [i].[name] AS [IndexName],
                  [i].[index_id],
                  [s].[user_seeks] + [s].[user_scans] + [s].[user_lookups] AS [Reads],
                  [s].[user_updates] AS [Writes],
                  CASE
                       WHEN [s].[user_updates] > [s].[user_seeks] + [s].[user_scans] + [s].[user_lookups] THEN
                           [s].[user_updates] - ([s].[user_seeks] + [s].[user_scans] + [s].[user_lookups])
                       ELSE ([s].[user_seeks] + [s].[user_scans] + [s].[user_lookups]) - [s].[user_updates] END AS [delta],
                  [i].[type_desc] AS [IndexType],
                  [i].[fill_factor] AS [FillFactor],
                  [i].[has_filter],
                  [i].[filter_definition],
                  [s].[last_user_scan],
                  [s].[last_user_lookup],
                  [s].[last_user_seek],
                  [idx_cols].[IndexColumns],
                  [idx_cols].[IncludedColumns],
                  [fk].[primary_table],
                  [fk].[pk_column_name],
                  [fk].[fk_constraint_name]
  FROM            [sys].[dm_db_index_usage_stats] AS [s] WITH (NOLOCK)
 INNER JOIN       [sys].[indexes] AS [i] WITH (NOLOCK)
    ON [s].[object_id] = [i].[object_id]
 INNER JOIN       [sys].[objects] [o] WITH (NOLOCK)
    ON [s].[object_id] = [o].[object_id]
 OUTER APPLY      (   SELECT       DISTINCT [x].[TblName],
                                            [x].[IndexName],
                                            [x].[IsPrimaryKey],
                                            [x].[IsUniqueConstraint],
                                            [x].[IsUnique],
                                            --,size.IndexSizeKB
                                            [c].[IndexColumns],
                                            [ci].[IncludedColumns],
                                            [cc].[ComputedColumns],
                                            [x].[FilterDefinition]
                        FROM       [ColInfo] [x]
                       CROSS APPLY (   SELECT STUFF([sq].[strXML], 1, 2, '') AS [IndexColumns]
                                         FROM (   SELECT ', ' + ISNULL([x2].[ColName], '')
                                                    FROM [ColInfo] [x2]
                                                   WHERE [x].[TblName]        = [x2].[TblName]
                                                     AND [x].[IndexName]      = [x2].[IndexName]
                                                     AND [x2].[IsIncludedCol] = 0
                                                   ORDER BY [x2].[key_ordinal]
                                                  FOR XML PATH('')) [sq]([strXML]) ) [c]
                       OUTER APPLY (   SELECT STUFF([sq].[strXML], 1, 2, '') AS [IncludedColumns]
                                         FROM (   SELECT ', ' + ISNULL([x2].[ColName], '')
                                                    FROM [ColInfo] [x2]
                                                   WHERE [x].[TblName]        = [x2].[TblName]
                                                     AND [x].[IndexName]      = [x2].[IndexName]
                                                     AND [x2].[IsIncludedCol] = 1
                                                   ORDER BY [x2].[key_ordinal]
                                                  FOR XML PATH('')) [sq]([strXML]) ) [ci]
                       OUTER APPLY (   SELECT STUFF([sq].[strXML], 1, 2, '') AS [ComputedColumns]
                                         FROM (   SELECT ', ' + ISNULL([x2].[ColName], '')
                                                    FROM [ColInfo] [x2]
                                                   WHERE [x].[TblName]        = [x2].[TblName]
                                                     AND [x].[IndexName]      = [x2].[IndexName]
                                                     AND [x2].[IsComputedCol] = 1
                                                   ORDER BY [x2].[key_ordinal]
                                                  FOR XML PATH('')) [sq]([strXML]) ) [cc]
                       WHERE       [x].[TblName] = [o].[name]
                         AND       [x].[IndexName]     = [i].[name]) [idx_cols]
  LEFT OUTER JOIN (   SELECT            SCHEMA_NAME([tab].[schema_id]) + '.' + [tab].[name] AS [table],
                                        [col].[column_id],
                                        [col].[name] AS [column_name],
                                        CASE
                                             WHEN [fk].[object_id] IS NOT NULL THEN '>-'
                                             ELSE NULL END AS [rel],
                                        SCHEMA_NAME([pk_tab].[schema_id]) + '.' + [pk_tab].[name] AS [primary_table],
                                        [pk_col].[name] AS [pk_column_name],
                                        [fk_cols].[constraint_column_id] AS [NO],
                                        [fk].[name] AS [fk_constraint_name],
                                        [tab].[name] AS [tbl_name]
                        FROM            [sys].[tables] [tab]
                       INNER JOIN       [sys].[columns] [col]
                          ON [col].[object_id]            = [tab].[object_id]
                        LEFT OUTER JOIN [sys].[foreign_key_columns] [fk_cols]
                          ON [fk_cols].[parent_object_id] = [tab].[object_id]
                         AND [fk_cols].[parent_column_id] = [col].[column_id]
                        LEFT OUTER JOIN [sys].[foreign_keys] [fk]
                          ON [fk].[object_id]             = [fk_cols].[constraint_object_id]
                        LEFT OUTER JOIN [sys].[tables] [pk_tab]
                          ON [pk_tab].[object_id]         = [fk_cols].[referenced_object_id]
                        LEFT OUTER JOIN [sys].[columns] [pk_col]
                          ON [pk_col].[column_id]         = [fk_cols].[referenced_column_id]
                         AND [pk_col].[object_id]         = [fk_cols].[referenced_object_id]
                       WHERE            [fk].[object_id] IS NOT NULL) [fk]
    ON [fk].[tbl_name] = [o].[name]
   AND [idx_cols].[IndexColumns] LIKE '%' + [fk].[column_name] + '%'
 WHERE            [o].[type] = 'U' -- user table
   AND            [i].[index_id]        = [s].[index_id]
   AND            [s].[database_id]     = DB_ID()
   AND            [o].[name]            = 'child'
 --AND i.name IN
 --	(
 --	N'NCIX_Entry_COL_ET_accounting_period',
 --	N'NCIX_Entry_COL_ET_entry_type',
 --	N'NCIX_Entry_COL_ET_predefined_entry',
 --	N'NCIX_Entry_COL_ET_bmc_user_profile',
 --	N'NCIX_Entry_COL_ET_currency',
 --	N'NCIX_Entry_COL_ET_entry_address'
 --	)

 ORDER BY [delta] DESC
--ORDER BY user_seeks + user_scans + user_lookups DESC  -- Order by reads
--ORDER BY s.user_updates DESC OPTION   				 -- Order by writes
OPTION (RECOMPILE);
