0

Update: I Solved this. Obviously I reinvented the wheel, but I did not immediately find the answer where I searched.

Given there is another question exactly the same as mine, but that does not answer my question, I will try to be very clear. My question is not answered because the answers do not indicate how to accomplish my task. I don't really care how I accomplish it, but there has to be a way.

I want the ability to count occurrences by level of any two discrete columns in an arbitrary table. I want to store the results for later reference because the query takes a long time to run.

The table name and two column names should be definable.

Based on a lot of research, it appears that a function, not a procedure should be used, but I am more interested in what happens, not how it happens.

DROP FUNCTION IF EXISTS O_E_1
GO
DROP TABLE IF EXISTS TestTable
GO

CREATE FUNCTION O_E_1
    (@feature NVARCHAR(128), @table NVARCHAR(128))
RETURNS TABLE
AS
   RETURN
       (SELECT 
            COUNT(DISTINCT [PersonID]) AS count_person, 
            @feature AS feature, [HasT2DM] AS target
        FROM
            dbo.@table
        GROUP BY
            [@feature], [HasT2DM]);
GO

SELECT * 
INTO TestTable 
FROM  O_E_1('Diagnosis', 'PatientDiagnoses')
go

I hope that with a little bit of work, I can accomplish this.

I have a version that does this in a procedure using dynamic SQL but unfortunately, I don't see how to save that result to a table. If someone wants to tell me how to save the results of a dynamic SELECT to a table in my schema, that would accomplish what I need.

Here is the procedure version with dynamic SQL. Also included is how I am trying to store the results into a table.

BEGIN

SET NOCOUNT ON;
DECLARE @cmd NVARCHAR(max)

set @cmd = '
       (SELECT 
            COUNT(DISTINCT [PersonID]) AS count_person, 
            [' + @feature + '] AS feature, [HasT2DM] AS target
        FROM
            dbo.[' + @table + ']
        GROUP BY
            [' + @feature + '], [HasT2DM])
            '
EXEC sp_executesql @cmd
END
GO

 O_E_1 @feature = 'Diagnosis', @table = 'PatientDiagnoses'

SELECT * 
INTO TestTable 
FROM  (O_E_1 @feature = 'Diagnosis', @table = 'PatientDiagnoses')
GO

I was able to code the answer I need. Here it is.

DROP PROCEDURE IF EXISTS O_E_1
GO
DROP TABLE IF EXISTS TestTable
GO

CREATE PROCEDUre O_E_1

@feature NVARCHAR(128),
 @table NVARCHAR(128)

AS

BEGIN

SET NOCOUNT ON;
DECLARE @cmd NVARCHAR(max)

set @cmd = '
       (SELECT 
            COUNT(DISTINCT [PersonID]) AS count_person, 
            [' + @feature + '] AS feature, [HasT2DM] AS target
        FROM
            dbo.[' + @table + ']
        GROUP BY
            [' + @feature + '], [HasT2DM])
            '
EXEC sp_executesql @cmd
END
GO


 DROP TABLe IF EXISTS RESULT
 CREATE TABLE Result
 (count_person numeric,
  feature      varchar(128),
  target       varchar(128)
  )

INSERT Result EXEC O_E_1 @feature = 'Diagnosis', @table = 'PatientDiagnoses'

Select TOP 100 * FROM RESULT
Harlan Nelson
  • 1,394
  • 1
  • 10
  • 22
  • 2
    You can't unless you know the table list upfront to make a huge static IF ELSE statement and [dynamic SQL is not allowed inside functions](https://stackoverflow.com/a/32868841/5070879) – Lukasz Szozda Aug 02 '19 at 19:51
  • 2
    You need dynamic SQL, and for that you need to do it in a SP – Brad Aug 02 '19 at 19:53
  • [SELECT * FROM @tablename](http://www.sommarskog.se/dynamic_sql.html#Dyn_table) – Lukasz Szozda Aug 02 '19 at 19:54
  • 3
    Whenever you find the need to start passing table names like this it is almost always a sign of less than ideal design. – Sean Lange Aug 02 '19 at 19:57
  • @SeanLange I am interested in what you mean by less than Ideal. – Harlan Nelson Aug 02 '19 at 20:03
  • @Brad Can I accomplish my goal with a procedure? – Harlan Nelson Aug 02 '19 at 20:04
  • 2
    It is usually a sign that the tables should be normalized. When you have a bunch of tables with the same structure you can almost always make things easier by adding one new column to the table to allow to identify the group it belongs to. This is a much better approach over having each group be in an identical table but with a name that identifies it. – Sean Lange Aug 02 '19 at 20:08
  • @SeanLange I don't even care about creating a table so much. But I need to store the result because It takes so long to generate it. – Harlan Nelson Aug 02 '19 at 20:12
  • I don't understand what you mean. You are passing in a table name. – Sean Lange Aug 02 '19 at 20:21
  • You spent a lot of time researching and writing this question and you never googled "SQL Server save result of dynamic sql to table"? Anyway here is you answer: https://smehrozalam.wordpress.com/2009/10/14/t-sql-using-result-of-a-dynamic-sql-query-in-a-variable-or-table/ . P.S. As others have said, there is no way do it from the function. You can also Google "SQL Server save result of SP to table" to get this: https://stackoverflow.com/questions/653714/insert-results-of-a-stored-procedure-into-a-temporary-table – Alex Aug 02 '19 at 21:04
  • @Alex I did a lot of googling, and reading through articles like lukasz telling me it was impossible. That clutter was hard to cut through. But, as you point out, not only was it possible, but the solution was fairly trivial. – Harlan Nelson Aug 02 '19 at 21:25
  • No probs. Lukasz Szozda and SeanLange do make an ambiguously valid point though, specifically: IF you do have many tables with **identical** schema, they should ideally be combined into one partitioned table or a View. This will simplify querying these tables significantly. The view solution is linked to by Lukasz Szozda – Alex Aug 02 '19 at 21:35

0 Answers0