I have a select statement I want to make. I want to select
SELECT COLUMN_NAME AS FieldName FROM
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'table1'
However I want to create another column named Value which is a particular row in table1
so I have rows of the column name and the corresponding single value. Any thoughts on how to approach this?
The following query produces a value (the minimum) for each column:
SELECT '''select '+COLUMN_NAME+''' AS FieldName, (select cast(MIN('+COLUMN_NAME+') as varchar(8000)) from '+const.tablename+')'
FROM INFORMATION_SCHEMA.COLUMNS c cross join
(select 'AllCurveNames' as tablename) const
WHERE c.TABLE_NAME = const.tablename
However, this produces a separate query for each row. To combine them together, you need a string aggregate concatenation. This is how you would do it in SQL Server:
declare #sql varchar(max);
SELECT #sql = (select 'select '''+COLUMN_NAME+''' AS FieldName, (select cast(MIN('+COLUMN_NAME+') as varchar(8000)) from '+const.tablename + ') union all '
FROM INFORMATION_SCHEMA.COLUMNS c cross join
(select WHATEVER as tablename) const
WHERE c.TABLE_NAME = const.tablename
for xml path('')
);
select #sql = LEFT(#sql, len(#sql) - 9);
exec(#sql);
Use a cross join, which is implicit if you just select from two tables with no join (i.e., from t1, t2):
SELECT COLUMN_NAME AS FieldName,
Table1.MyField
FROM
INFORMATION_SCHEMA.COLUMNS, Table1
WHERE
TABLE_NAME = 'table1'
AND
MyTable.ID = 123
I actually came up with a bit of a crazy solution but it works:
declare #tbl_name as varchar(255)
declare #field as varchar(255)
declare #val as varchar(255)
declare #SQL as nvarchar(4000)
create table #tbl ( [FieldName][varchar](255), [FieldVal][varchar](255))
set #tbl_name = 'table1'
DECLARE mah_cursor CURSOR FAST_FORWARD
FOR
SELECT COLUMN_NAME FROM
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #tbl_name
OPEN mah_cursor
FETCH NEXT FROM mah_cursor INTO #field
WHILE ##FETCH_STATUS = 0
BEGIN
set #SQL = 'set #val = (Select top 1 ' + #field + ' from ' + #tbl_name + ')'
print #SQL
exec sp_executesql #query = #SQL, #params = N'#val varchar(255) OUTPUT', #val = #val OUTPUT
insert into #tbl ([FieldName],[FieldVal] ) values (#field, #val)
FETCH NEXT FROM mah_cursor INTO #field
END
CLOSE mah_cursor
DEALLOCATE mah_cursor
select * from #tbl
drop table #tbl
It loops through each value and adds it. The Fast_Forward feature optimizes the query for high performance
Related
I am currently asked to validate the result of a global search which to find all records containing some keywords cross whole database. To do so, I need to check all the rows in each table that have keywords. The result for this global search is ready and partially of the result looks like the one below:
table_name
column_name
keyword
cnt
Wf_Process
Name_EN
FEC
11
Wf_Process
FTABLENAME
GB
14
ICCClass
Name_EN
GB
4
What I am trying to do is using the 'like' operator to extract all the data in each table where columns containing keywords. That is, I will use query such as:
select distinct Name_EN, FTABLENAME from Wf_Process where Name_EN like '%FEC%' or FTABLENAME like '%GB%'
and
select distinct Name_EN from ICCClass where Name_EN like '%GB%'
to pull out all data I need in whole database. If I only have three records, then it is not a problem. However my result returned over thousands tables have more than 10K rows containing keywords in total. Therefore, I was trying to use a loop to do this mission but I failed.
My question therefore is, does anyone have any idea to write a loop to do the 'like' search for all the tables in one time? Or is there another way rather than loop can do this in SQL Server?
Thank you very much!
You need dynamic SQL for this. You can generate a big UNION ALL query of all the tables together.
DECLARE #sql nvarchar(max) = (
SELECT STRING_AGG(CAST('
SELECT
' + QUOTENAME(con.table_name, '''') + ' table_name,
' + QUOTENAME(con.column_name, '''') + ' column_name,
' + QUOTENAME(con.keyword, '''') + ' keyword,
COUNT(*) cnt
FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) + ' t
WHERE t.' + QUOTENAME(c.name) + ' LIKE ' + QUOTENAME('%' + con.keyword + '%', '''')
AS nvarchar(max)), '
UNION ALL')
FROM YourConditions con
JOIN sys.tables t ON t.table_name
JOIN sys.schemas s ON s.schema_id = t.schema_id
JOIN sys.columns c ON c.object_id = t.object_id
WHERE t.name = con.table_name
AND c.name = con.column_name
);
PRINT #sql; -- your friend
EXEC sp_executesql #sql;
There are more efficient ways to do this if there are many columns or keywords per table, but this should get you started.
The question looks odd, thou can be done via dynamic sql, but not as a regular solution more like a one off or POC/test.
use tempdb
GO
drop table if exists search_result
go
create table search_result (
table_name sysname
,column_name sysname
,keyword varchar(100))
go
insert into search_result values
('Wf_Process', 'Name_EN', 'FEC')
,('Wf_Process' , 'FTABLENAME', 'GB')
,('ICCClass', 'Name_EN', 'GB')
GO
drop table if exists result
create table result (val varchar(500))
go
declare #col sysname
declare #tab sysname
declare #kw varchar(100)
declare #sql varchar(1000)
while exists (select * from search_result)
begin
select top 1
#tab = table_name
, #col = column_name
, #kw = keyword
from search_result
set #sql = concat('insert into result select ', #col, ' from ', #tab, ' where ', #col, ' like ''%', #kw, '%''' )
print(#sql)
exec (#sql)
delete from search_result
where table_name = #tab and column_name = #col and keyword = #kw
end
GO
select * from result
--initially trying to get all the column name with its respective table name, finding out if there is that particular keyword in all table,
--if yes, insert into temp table, if there aint keyword, it will insert the record too but the count of record will be zero.
--trying to make it dynamic and running it inside the loop by assigning row number to each table with different column.
IF OBJECT_ID('tempdb..#TEMP') IS NOT NULL
DROP TABLE #TEMP
CREATE TABLE #TEMP (TABLE_NAME NVARCHAR(200), COLUMN_NAME NVARCHAR(200), KEYWORD NVARCHAR(200), CNT INT)
DECLARE #TABLE NVARCHAR(200)
DECLARE #TABLE_ID INT
SET #TABLE_ID = 1
DECLARE #TABLE_NAME NVARCHAR (200)
DECLARE #FOR_LOOP INT
DECLARE #COLUMN NVARCHAR(200)
DECLARE #COLUMN_NAME NVARCHAR(200)
--TOTAL NO OF RECORDS FOR LOOP
SET #FOR_LOOP = (SELECT COUNT(*)
FROM SYS.tables T
JOIN SYS.all_columns C ON T.object_id = C.object_id
JOIN INFORMATION_SCHEMA.TABLES S ON S.TABLE_NAME = T.name)
DECLARE #STRINGS NVARCHAR(200)
SET #STRINGS = '%FEC%' --------->ENTER YOUR KEYWORD HERE, TRY ONE AT A TIME
DECLARE #COUNT INT
WHILE #TABLE_ID <= #FOR_LOOP
BEGIN
SET #TABLE = (SELECT CAST(TABLE_NAME AS NVARCHAR(200))
FROM
(SELECT ROW_NUMBER()OVER(ORDER BY T.NAME) TABLE_ID
,S.TABLE_SCHEMA SCHEMA_NAME ,T.NAME TABLE_NAME, C.name COLUMN_NAME
FROM SYS.tables T
JOIN SYS.all_columns C ON T.object_id = C.object_id
JOIN INFORMATION_SCHEMA.TABLES S ON S.TABLE_NAME = T.name)A
WHERE TABLE_ID = #TABLE_ID)
SET #TABLE_NAME = '['+#TABLE+']'
SET #COLUMN = (SELECT CAST(COLUMN_NAME AS NVARCHAR(200))
FROM
(SELECT ROW_NUMBER()OVER(ORDER BY T.NAME) TABLE_ID
,S.TABLE_SCHEMA SCHEMA_NAME ,T.NAME TABLE_NAME, C.name COLUMN_NAME
FROM SYS.tables T
JOIN SYS.all_columns C ON T.object_id = C.object_id
JOIN INFORMATION_SCHEMA.TABLES S ON S.TABLE_NAME = T.name)A
WHERE TABLE_ID = #TABLE_ID)
SET #COLUMN_NAME = '['+#COLUMN+']'
DECLARE #EXEC NVARCHAR(200) = 'SELECT ' + #COLUMN_NAME +' FROM ' + #TABLE_NAME + ' WHERE ' + #COLUMN_NAME + ' LIKE ' + ''''+#STRINGS+''''
--THERE MUST BE ANOTHER WAY TO REPLACE SP_EXECUTESQL FOR BETTER PERFORMANCE, AS IT WILL BE EXECUTED AS MANY TIMES AS THERE ARE RECORDS IN #FOR_LOOP
EXEC SP_EXECUTESQL #EXEC
SET #COUNT = (SELECT ##ROWCOUNT)
IF (SELECT ##ROWCOUNT) >=1
BEGIN
INSERT INTO #TEMP VALUES
(#TABLE_NAME, #COLUMN_NAME, #STRINGS, #COUNT)
SET #TABLE_ID = #TABLE_ID + 1
END
ELSE
--DONT KNOW WHY THIS ELSE PART IS NOT TOUCHED, WHEREAS I THINK IT SHOULD HAVE
BEGIN
PRINT 'RECORD NOT FOUND'
END
END
GO
--AFTER THE ABOVE BLOCK IS EXECUTED THEN TRY RUNNING BELOW ONE
SELECT *FROM #TEMP WHERE CNT>0
--THERE MAY BE MULTIPLE ERROS, MUST BE EDITED AND CAN MAKE IT AS A PROCEDURE TOO.
I have a SQL database with 60+ tables, almost all of which are populated with a CLIENTID field. I want to count the number of unique client IDs in each table.
The results I'm looking for are:
TABLE_NAME; CLIENTID_COUNT
dbo.HISTORY; 650
dbo.VISITS; 596
dbo.SALES; 1053
...; ...
This seems like it should be so simple but I've been playing around with cursors for hours and can't figure this one out. Please help!
IF OBJECT_ID('tempdb..#temp_RESULTS') IS NOT NULL DROP TABLE #temp_RESULTS
CREATE TABLE #TEMP_RESULTS
(
TABLENAME VARCHAR(MAX),
CLIENTCNT BIGINT
)
DECLARE #TABLENAME VARCHAR(MAX)
DECLARE #command VARCHAR(MAX)
IF OBJECT_ID('tempdb..#temp_PROCESS') IS NOT NULL DROP TABLE #temp_PROCESS
SELECT * INTO #TEMP_PROCESS FROM sys.tables
WHILE EXISTS(SELECT * FROM [#TEMP_PROCESS])
BEGIN
SET #TABLENAME = (SELECT TOP 1 [NAME] FROM [#TEMP_PROCESS])
SET #command = ('SELECT ''' + #TABLENAME + ''', COUNT(DISTINCT CLIENTID) AS CLIENTCNT FROM ' + #TABLENAME)
SELECT #command
INSERT INTO #TEMP_RESULTS
EXEC(#command)
DELETE FROM [#TEMP_PROCESS] WHERE [NAME] = #TABLENAME
END
SELECT * FROM [#TEMP_RESULTS]
Assuming the column is exactly ClientId in every table, you should be able to use this as is:
DROP TABLE IF EXISTS #clientId
CREATE TABLE #clientId
(
TableName nvarchar(1000),
ClientIdCount bigint
)
DECLARE #TableName nvarchar(1000);
DECLARE #CurrentQuery nvarchar(2000);
DECLARE result_cursor CURSOR local fast_forward FOR
SELECT DISTINCT
'['+TABLE_SCHEMA + '].[' + TABLE_NAME + ']'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
COLUMN_NAME = 'ClientId'
OPEN result_cursor
FETCH NEXT FROM result_cursor into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #CurrentQuery = 'SELECT ''' + #TableName + ''', COUNT(DISTINCT ClientId) FROM ' + #TableName
--print #CurrentQuery
INSERT INTO
#clientId
(
TableName,
ClientIdCount
)
EXEC(#CurrentQuery)
FETCH NEXT FROM result_cursor into #TableName
END
--end loop
--clean up
CLOSE result_cursor
DEALLOCATE result_cursor
GO
SELECT
*
FROM
#clientId
You could use dynamic sql.
This will read through your system tables, find those that have a ClientID column, and build the text of a query that's in the general shape of 'Select Count(DISTINCT ClientID)' from each table.
DECLARE #SQLQuery as nvarchar(max) = ''
------------------------------------
-- GET THE TABLES THAT HAVE A CLIENTID FROM SCHEMA
SELECT #SQLQuery = #SQLQuery + qryTxt FROM (
SELECT DISTINCT 'SELECT ''' + tables.name + ''', COUNT(DISTINCT CLIENTID) FROM ' + tables.name + ' UNION ' AS qryTxt
FROM sys.columns left join sys.tables on columns.object_id = tables.object_id where columns.name = CLIENTID AND isnull(tables.name, '') <> '') subquery
------------------------------------
-- REMOVE THE LAST 'UNION' KEYWORD FROM SQLQUERY
SET #SQLQuery = left(#sqlQuery, len(#sqlQuery) - 5)
------------------------------------
-- EXECUTE
execute sp_executesql #SQLQuery
I really dislike cursors and loops. Even though this is not going to be much difference for a performance perspective I like to share how you can leverage the system tables and dynamic sql to avoid using a cursor, while loop or temp tables for something like this.
This code is literally all you need to to do this.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'select TableName = ''' + t.name + ''', ClientID_Count = count(distinct clientID)
from ' + QUOTENAME(t.name) + ' UNION ALL '
from sys.tables t
join sys.columns c on c.object_id = t.object_id
where c.name = 'clientID'
select #SQL = left(#SQL, len(#SQL) - 10) --removes the last UNION ALL
select #SQL
--once your comfortable the dynamic sql is correct just uncomment the line below.
--exec sp_executesql #SQL
A similar pattern to other answers here, but this is how I would tackle it:
IF OBJECT_ID('#Tables', 'U') IS NOT NULL
DROP TABLE #Tables;
SELECT ID = IDENTITY(INT, 1, 1),
SchemaName = OBJECT_SCHEMA_NAME([object_id]),
TableName = OBJECT_NAME([object_id]),
ColumnName = name,
DistinctCount = 0
INTO #Tables
FROM sys.columns
WHERE name = 'CLIENTID';
DECLARE #ID INT = 1,
#MaxID INT = (SELECT MAX(ID) FROM #Tables);
WHILE #ID < #MaxID
BEGIN;
DECLARE #SQLCommand VARCHAR(MAX);
SELECT #SQLCommand = FORMATMESSAGE('
UPDATE #Tables SET DistinctCount = (
SELECT COUNT(DISTINCT %s) FROM %s.%s
)
WHERE ID = %i;',
QUOTENAME(ColumnName), QUOTENAME(SchemaName), QUOTENAME(TableName), ID)
FROM #Tables
WHERE ID = #ID;
EXEC (#SQLCommand);
SET #ID += 1;
END;
SELECT *
FROM #Tables;
I have a final temporary table (#tempTable) with unknown columns number.
My final select is like this, it works :
SELECT temp.* FROM #tempTable temp
But instead of a '*' I would like to call each columns individually :
SELECT temp.col1, temp.col2 FROM #tempTable temp
To do so I need to iterate through my columns names and create a procedure, I tried something like this :
DECLARE #ColName VARCHAR(255)
SELECT #ColName = min(name) FROM tempdb.sys.columns
WHERE object_id = Object_id('tempdb..#TEMPTABLE');
WHILE #ColName is not null
BEGIN
-- i need to do it all in once and not each time....
declare #sql varchar(max) = 'SELECT tp.'+'#COlName'+'FROM #TEMPTABLE tp'
exec(#sql)
-- Increment the value, how to go to next column ?
select #ColName = min(name) FROM tempdb.sys.columns WHERE object_id =
Object_id('tempdb..#TEMPTABLE') > #ColName -- does not work because it is a string (column name)
END
Try this:
DECLARE #ColName VARCHAR(2000) = 'select '
SELECT #ColName = #ColName + ' temp.' + name + ',' FROM tempdb.sys.columns
WHERE object_id = Object_id('tempdb..#TEMPTABLE')
--delete last character, which is comma and append table name
#ColName = substring(#ColName, 1, LEN(#ColName) - 1) + ' from #TEMPTABLE temp'
exec(#ColName)
This query construct whole table list combined in select ... from ... statement. I increased size of the varchar variable, so it can accomodate long queries.
Also, IMO variable name such as #sql or #query would be more meaningful.
A set based approach
IF OBJECT_ID('tempdb..#TEMPTABLE','U') IS NOT NULL
DROP TABLE #TEMPTABLE;
CREATE TABLE #TEMPTABLE (
Id INT IDENTITY(1,1)
,Col1 INT
,Col2 BIGINT
,Col3 BIGINT
,Col4 DATETIME
,Col5 DATETIME
) ;
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = N'SELECT ' + SUBSTRING((
SELECT N', temp.' + S.name
FROM
tempdb.sys.columns S
WHERE
S.object_id = OBJECT_ID('tempdb..#TEMPTABLE')
ORDER BY
S.column_id
FOR XML PATH('')
)
,2
,200000
) + N' FROM #TEMPTABLE temp'
EXEC sys.sp_executesql #SQL
I have this SQL query
SELECT table_name
INTO #LukaTestTable
FROM information_schema.columns
WHERE column_name = 'GUID'
ORDER BY TABLE_NAME ;
How get the value of the column GUID in all tables with the name from TABLE_NAME?
Or can I get table like?
TABLE_NAME GUID_VALUE
In order to be able to query a table before you know what table you want you have to use dynamic queries. If you have an arbitrary number of tables, in SQL Server you could achieve this with cursors:
DECLARE
#column VARCHAR(256) = 'GUID',
#table VARCHAR(256),
#query VARCHAR(4000);
DECLARE #Tables CURSOR LOCAL FAST_FORWARD
FOR
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = #column
ORDER BY TABLE_NAME;
OPEN #Tables
FETCH NEXT FROM #Tables INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = 'SELECT ' + #column + ' FROM ' + #table
EXEC(#query)
FETCH NEXT FROM #Tables INTO #table
END
CLOSE #Tables
DEALLOCATE #Tables;
If you're sure your 'GUID' column will have same data type - you can create a temp table and insert to it in WHILE loop and SELECT everything in one go at the end.
You can use dynamic sql like this:
declare #sql varchar(max) = cast (' ' as varchar(max));
select #sql = #sql +
(select ' select GUID from ' + quotename(table_name) + ' union all ' as 'text()'
from #LukaTestTable
for xml path(''));
set #sql = reverse(stuff(reverse(#sql), 1, 10, ''));
--print #sql
exec(#sql);
And if you want table_name as e separate column you should first save it in your #LukaTestTable
Try this below script using While loop and dynamic Sql
IF OBJECT_ID('tempdb..#GetSqlQuery') IS NOT NULL
DROP TABLE #GetSqlQuery
IF OBJECT_ID('tempdb..#GetSpecficcolumnvalue') IS NOT NULL
DROP TABLE #GetSpecficcolumnvalue
GO
CREATE TABLE #GetSqlQuery
(
ID INT IDENTITY
,SELECtQuery nvarchar(max)
,TableName varchar(200)
)
CREATE TABLE #GetSpecficcolumnvalue
(
ID INT IDENTITY
,GetValue nvarchar(max)
,TableName varchar(200)
)
INSERT INTO #GetSqlQuery(SELECtQuery,TableName)
SELECT 'SELECT GUID,'''+TABLE_NAME+''' As TableName FROM '+QUOTENAME(TABLE_NAME) AS SELECtQuery,QUOTENAME(TABLE_NAME) AS TableName
FROM(
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME ='GUID'
)dt
ORDER BY TABLE_NAME
DEclare #MinId INt,#MaxId INT,#Sql nvarchar(maX),#TableName varchar(1000)
SELECT #MinId =MIN(Id),#MaxId=MAX(ID) FROM #GetSqlQuery
WHILE (#MinId<=#MaxId)
BEgin
SELECT #Sql=SELECtQuery ,#TableName=TableName From #GetSqlQuery WHERE ID=#MinId
PRINT #Sql
INSERT INTO #GetSpecficcolumnvalue(GetValue,TableName)
EXEC (#Sql)
SET #MinId=#MinId+1
END
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) AS Seq,GetValue,TableName
FROM
(
SELECT *, ROW_NUMBER ()OVER(PArtition by GetValue,TableName ORDER BY
TableName) AS dup FROM #GetSpecficcolumnvalue
)dt where dt.dup=1
Table:
Col
------
Table1
table2
table3
Query:
select count(*)
from #tablename
I wanted to pass table1, table2, table3 as parameters for #tablename in the select query and get the count for each table
Desired output:
2 (table 1 count) 3 (table 2 count) 4 (table 3 count)
you can use dynamic sql and a cursor to run through them:
Create temp table for testing:
DECLARE #tablenametable TABLE(tablename VARCHAR(100));
INSERT INTO #tablenametable
VALUES('table1'), ('table2'), ('table3');
Use a cursor to run through all tablenames in the table
DECLARE #tablename VARCHAR(100);
DECLARE dbcursor CURSOR
FOR
SELECT tablename
FROM #tablenametable;
OPEN dbcursor;
FETCH NEXT FROM dbcursor INTO #tablename;
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #sql VARCHAR(MAX);
SET #sql = 'select count(*) from '+#tablename;
PRINT(#sql);
FETCH NEXT FROM dbcursor INTO #tablename;
END;
CLOSE dbcursor;
DEALLOCATE dbcursor;
Give the following results:
select count(*) from table1
select count(*) from table2
select count(*) from table3
Just change PRINT(#SQL) to EXEC(#SQL) when your happy with it
You can use dynamic sql query.
Query
declare #sql as varchar(max);
select #sql = stuff((
select ' union all '
+ 'select cast(count(*) as varchar(100))
+ ' + char(39) + '(' + [Col] +' Count)' + char(39)
+ ' as [table_counts] '
+ ' from ' + [col]
from [your_table_name]
for xml path('')
)
, 1, 11, ''
);
exec(#sql);
Find a demo here
As mentioned here, you have to use dynamic SQL.
First approach is where you specify table name yourself:
declare #tablename varchar(30), #SQL varchar(30)
set #tablename = 'Table1' --here you specify the name
set #SQL = concat('SELECT COUNT(*) FROM ', #tablename) --here you build the query
EXEC(#SQL)
Second approach lets you use table with names of tables:
declare #SQL varchar(8000)
set #SQL = ''
declare #TableNames table(name varchar(30))
insert into #TableNames values ('Table1'), ('Table2'), ('Table3')
--here you build the query
select #SQL = #SQL + ' SELECT ''' + name + ''' AS [TableName], COUNT(*) AS [Count] FROM ' + name + ' UNION ALL' from #TableNames
-- get rid of last "UNION ALL"
set #SQL = LEFT(#SQL, LEN(#SQL) - 10)
--execute the query
EXEC(#SQL)
The result of it will be:
TableName Count
Table1 3
Table2 6
Table3 4
You can use sys.dm_db_partition_stats like this [1]:
select
t.col tableName, sum(s.row_count) tableCount
from
yourTable t
join
sys.dm_db_partition_stats s
on
(object_name(s.object_id) = t.col )
and
(s.index_id < 2)
group by
t.col;
[1]. Related answer
One line output version will be:
select
sum(s.row_count), ' ('+t.col +' count) '
from
yourTable t
join
sys.dm_db_partition_stats s
on
(object_name(s.object_id) = t.col )
and
(s.index_id < 2)
group by
t.col
for xml path('');
output:
2 (Table1 count) 3 (table2 count) 4 (table3 count)