MSSQL - Counting dates from two columns grouping by external date range - sql-server

I have a simple table containing case number (ID), opening_date and end_date where end_date have null values (unfinished cases). It looks like this:
ID opening_date end_date
1 2021-01-04 2021-01-14
2 2021-01-04 2021-01-26
3 2021-01-14 2021-02-15
4 2021-02-01 NULL
5 2021-02-04 2021-02-26
6 2021-02-10 2021-02-15
I'm trying to write a select query which will show me simply by month/week or day (nevermind), how many cases were set up (opening_date) and how many were closed (end_date) per each month./week. The problem is that I cannot use opening or end date in filters because not every date from opening_date column is in end_date and vice versa. It should be specific date range generated separately as external table in first column or something like that, so if there's situation, where neither opening nor end date occurs (in a day/week/month), a row with zeros should be shown as in the first date below - The result of example by day:
date openings endings
2021-01-01 0 0
2021-01-02 0 0
2021-01-03 0 0
2021-01-04 2 0
2021-01-05 0 0
2021-01-06 0 0
2021-01-07 0 0
2021-01-08 0 0
2021-01-09 0 0
2021-01-10 0 0
2021-01-11 0 0
2021-01-12 0 0
2021-01-13 0 0
2021-01-14 1 1
2021-01-15 0 0
2021-01-16 0 0
2021-01-17 0 0
2021-01-18 0 0
2021-01-19 0 0
2021-01-20 0 0
2021-01-21 0 0
2021-01-22 0 0
2021-01-23 0 0
2021-01-24 0 0
2021-01-25 0 0
2021-01-26 0 1
2021-01-27 0 0
2021-01-28 0 0
2021-01-29 0 0
2021-01-30 0 0
2021-01-31 0 0
2021-02-01 1 0
2021-02-02 0 0
2021-02-03 0 0
2021-02-04 1 0
2021-02-05 0 0
2021-02-06 0 0
2021-02-07 0 0
2021-02-08 0 0
2021-02-09 0 0
2021-02-10 1 0
2021-02-11 0 0
2021-02-12 0 0
2021-02-13 0 0
2021-02-14 0 0
2021-02-15 0 2
2021-02-16 0 0
2021-02-17 0 0
2021-02-18 0 0
2021-02-19 0 0
2021-02-20 0 0
2021-02-21 0 0
2021-02-22 0 0
2021-02-23 0 0
2021-02-24 0 0
2021-02-25 0 0
2021-02-26 0 1
2021-02-27 0 0
2021-02-28 0 0
By months:
Month openings endings
2021-01 3 2
2021-02 3 3
Please help me. Thanks in advance.

You need a calendar table for this. You start with the calendar, and LEFT JOIN everything else.
To get the calculation for each day, we can unpivot and group, then count daily totals
You can have a real table. Or you can generate it on the fly, like this:
WITH
L0 AS ( SELECT c = 1
FROM (VALUES(1),(1),(1),(1),(1),(1),(1),(1),
(1),(1),(1),(1),(1),(1),(1),(1)) AS D(c) ),
L1 AS ( SELECT c = 1 FROM L0 A, L0 B, L0 C ),
Nums AS ( SELECT rownum = ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM L1 ),
Dates AS ( SELECT [date] = DATEADD(day, rownum, '20180101')
FROM Nums )
SELECT
d.[date],
openings = ISNULL(t.openings, 0),
endings = ISNULL(t.endings, 0)
FROM Dates d
LEFT JOIN (
SELECT v.AllDates,
openings = COUNT(IsOpen),
endings = COUNT(IsEnd)
FROM YourTable t
CROSS APPLY (VALUES
(opening_date, 1, NULL),
(end_date, NULL, 1)
) v(AllDates, IsOpen, IsEnd)
GROUP BY v.AllDates
) t ON t.AllDates = d.[date];

Related

SQL Pivot Table - Subqueries

I have a program that is logging the time a user spends on certain aspects, some are identified as specific "time". I'm struggling to get multiple lines of Grouped query results into a single line for each month as a "summary".
My current query:
SELECT
TotalMins = SUM(Minutes)
,DateMonth = MONTH(Date)
,ID1
,PC
FROM User_Time_Log
WHERE
(UserID = 1)
AND (YEAR(Date) = 2018)
GROUP BY
MONTH(Date)
,ID1
,PC1
Current results:
TotalMins DateMonth ID1 PC1
192 1 0 0
306 1 0 100
113 2 0 0
365 2 0 100
14 2 1 0
3 2 1 100
75 3 0 0
253 3 0 100
3 3 1 0
300 4 0 0
233 4 0 100
10 4 1 0
23 4 1 100
438 5 0 0
134 5 0 100
19 5 1 0
49 5 1 100
0 9 1 0
11 10 0 0
21 10 0 60
167 10 1 100
What I would like to do from this point is to create a table showing all 12 months, regardless of whether there is information within that month or not, and show the relative information within each row for that month. for example:
DateMonth NonID1 TimeID1 TimePC1 (Round((PC1/100)*TotalMins)) TimePC1ID1
1 192 0 306 0
2 113 14 365 3
3 75 3 253 0
4 300 10 233 23
5 438 19 134 49
6 0 0 0 0
7 0 0 0 0
8 0 0 0 0
9 0 0 0 0
10 11 0 13 167
11 0 0 0 0
12 0 0 0 0
What's the most efficient way to do this?
Note: I have also created a table to give me 1-12 as rows that I can use to give me the months that I need to use, where information is not within the user_time_log.
Here's a simple way to do what you're looking for:
First, create your table of month values. I made a simple temp table with a single column.
CREATE TABLE #Dates (MonthNum INT)
INSERT INTO #Dates
(
MonthNum
)
VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
Next, you can put your existing query into a CTE, then LEFT JOIN to your table of months. You'll want to put your columns into a SUM'd CASE statement, like so:
;WITH Aggregation AS
(
SELECT
TotalMins = SUM(Minutes)
,DateMonth = MONTH(Date)
,ID1
,PC1
FROM #User_Time_Log
WHERE
(UserID = 1)
AND (YEAR(Date) = 2018)
GROUP BY
MONTH(Date)
,ID1
,PC1
)
SELECT
d.MonthNum
,NonID1 = SUM(CASE WHEN ID1 = 0 THEN TotalMins ELSE 0 END)
,TimeID1 = SUM(CASE WHEN ID1 = 1 THEN TotalMins ELSE 0 END)
,TimePC1 = SUM(CASE WHEN ID1 = 0 THEN ROUND((PC1/100)*TotalMins,0) ELSE 0 END)
,TimePC1ID1 = SUM(CASE WHEN ID1 = 1 THEN ROUND((PC1/100)*TotalMins,0) ELSE 0 END)
FROM #Dates d
LEFT JOIN Aggregation a ON d.MonthNum = a.DateMonth
GROUP BY d.MonthNum
Output would then look like this:
MonthNum NonID1 TimeID1 TimePC1 TimePC1ID1
1 498 0 306 0
2 478 17 365 3
3 328 3 253 0
4 533 33 233 23
5 572 68 134 49
6 0 0 0 0
7 0 0 0 0
8 0 0 0 0
9 0 0 0 0
10 32 167 0 167
11 0 0 0 0
12 0 0 0 0
EDIT:
The ROUND() function call can be changed slightly to accomodate your need for decimal results. The first parameter of ROUND() is the expression you want to round, and the second is the number of decimal places to round to. Positive numbers indicate the number of places to the right of the decimal to round to. Negative numbers indicate the number of places to the left of the decimal to round to. So if you set it to 2, you'll get an answer rounded to the nearest hundredth.
But there's one more tweak we need. PC1 and TotalMins are both assumed to be INTs in my answer. So we have to give the SQL engine a little help so that it calculates the answer as a DECIMAL. By CAST()ing the INTs to DECIMALs, SQL will perform the arithmetic op as decimal math instead of integer math. You'd just have to change TimePC1 and TimePC1ID1 like so:
,TimePC1 = SUM(CASE WHEN ID1 = 0 THEN ROUND((CAST(PC1 AS DECIMAL)/100)*CAST(TotalMins AS DECIMAL),2) ELSE 0 END)
,TimePC1ID1 = SUM(CASE WHEN ID1 = 1 THEN ROUND((CAST(PC1 AS DECIMAL)/100)*CAST(TotalMins AS DECIMAL),2) ELSE 0 END)
Then the output looks like this:
MonthNum NonID1 TimeID1 TimePC1 TimePC1ID1
1 498 0 306.000000 0.000000
2 478 17 365.000000 3.000000
3 328 3 253.000000 0.000000
4 533 33 233.000000 23.000000
5 572 68 134.000000 49.000000
6 0 0 0.000000 0.000000
7 0 0 0.000000 0.000000
8 0 0 0.000000 0.000000
9 0 0 0.000000 0.000000
10 32 167 12.600000 167.000000
11 0 0 0.000000 0.000000
12 0 0 0.000000 0.000000

T-SQL to join system tables to values in user tables SYS.TABLES, SYS.TYPES, SYS.COLUMNS

I have this query that selects the tables like CODE_. I want to join these results to each CODE table like CODE_COUNTRY, CODE_COUNTY to list the value of the SHORT_DESC, it will be values like: United States, Mexico for Country; Brown, Green for County; Male, Female For Gender*. The value in the SHORT_DESC matches the value in the Transformations Table PC_Column*. So I need to join to the Transformations table to find the columns that match. And do left join, right joins to show columns that don't match either database. How do I find the system column to join to the Transformations table?
SELECT tb.[schema_id] AS 'Schema'
,tb.[OBJECT_ID] AS 'TableObj'
,tb.[NAME] AS 'TableName'
,C.NAME as 'Column'
,T.name AS 'Type'
,C.max_length
,C.is_nullable
FROM
SYS.COLUMNS C
INNER JOIN
SYS.TABLES tb ON tb.[object_id] = C.[object_id]
INNER JOIN
SYS.TYPES T ON C.system_type_id = T.user_type_id
--INNER JOIN
-- Bridge_test.dbo.Transformations TF ON TF.PC_Column = C.NAME
WHERE
tb.[is_ms_shipped] = 0
AND tb.[NAME] LIKE '%code_%'
AND C.name = 'SHORT_DESC'
--C.NAME LIKE '%country%'
ORDER BY
tb.[Name]
*Note: these are the columns to add to this query
query result
Schema TableObj TableName Column Type max_length is_nullable *SHORT_DESC Value (from CODE_ table), *PC_Column (from Transformations table)
1 1826105546 CODE_COUNTRY SHORT_DESC nvarchar 20 0 United States, USA
1 2018106230 CODE_COUNTY SHORT_DESC nvarchar 20 0 Mexico, Mexico
For example, the value in the SHORT_DESC should match the PC_Column
CODE_VALUE_KEY CODE_VALUE SHORT_DESC MEDIUM_DESC LONG_DESC STATUS
1001 1001 Autauga Autauga Autauga A
1003 1003 Baldwin Baldwin Baldwin A
1005 1005 Barbour Barbour Barbour A
1007 1007 Bibb Bibb Bibb A
1009 1009 Blount Blount Blount A
Transformations Table
GM_Column Value Note1 F4 PC_Table_Column PC_Table PC_Column Value1 Note2 F10
Ugender M NULL = demographics_gender demographics gender Male NULL NULL
Ugender F NULL = demographics_gender demographics gender Female NULL NULL
Ugender U NULL = demographics_gender demographics gender Unknown NULL NULL
Umarstat D NULL = demographics_marital_status demographics marital_status Divorced NULL NULL
Umarstat M NULL = demographics_marital_status demographics marital_status Married NULL NULL
Umarstat O NULL = demographics_marital_status demographics marital_status Other NULL NULL
Umarstat S NULL = demographics_marital_status demographics marital_status Single NULL NULL
Sytem Tables --queried system tables to find a common column with user data and don't see a common column to join to the user data tables
SELECT * FROM sys.tables WHERE name LIKE '%code%'
/*
name object_id principal_id schema_id parent_object_id type type_desc create_date modify_date is_ms_shipped is_published is_schema_published lob_data_space_id filestream_data_space_id max_column_id_used lock_on_bulk_load uses_ansi_nulls is_replicated has_replication_filter is_merge_published is_sync_tran_subscribed has_unchecked_assembly_data text_in_row_limit large_value_types_out_of_row is_tracked_by_cdc lock_escalation lock_escalation_desc
CODE_SOURCETYPE 5195785 NULL 1 0 U USER_TABLE 45:44.0 16:28.9 0 0 0 0 NULL 18 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_CONTROLTYPE 8671795 NULL 1 0 U USER_TABLE 45:37.8 16:28.9 0 0 0 0 NULL 17 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_SPONSORSTATUS 21195842 NULL 1 0 U USER_TABLE 45:44.1 16:29.0 0 0 0 0 NULL 19 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_COUNTRY 24671852 NULL 1 0 U USER_TABLE 45:37.8 16:29.0 0 0 0 0 NULL 24 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_SPONSORTYPE 37195899 NULL 1 0 U USER_TABLE 45:44.1 16:29.2 0 0 0 0 NULL 17 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_COUNTY 40671909 NULL 1 0 U USER_TABLE 45:37.9 16:29.2 0 0 0 0 NULL 18 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_STATE 53195956 NULL 1 0 U USER_TABLE 45:44.2 16:29.3 0 0 0 0 NULL 19 0 1 0 0 0 0 0 0 0 0 0 TABLE
CODE_CREDCARDTYPE 56671966 NULL 1 0 U USER_TABLE 45:38.0 16:29.3 0 0 0 0 NULL 17 0 1 0 0 0 0 0 0 0 0 0 TABLE
*/
SELECT * FROM sys.objects WHERE type = 'U' --user tables
/*
has table name
name object_id principal_id schema_id parent_object_id type type_desc create_date modify_date is_ms_shipped is_published is_schema_published
ADDRESSSCHEDULE 7671075 NULL 1 0 U USER_TABLE 03:10.6 03:14.2 0 0 0
ADVANCENAME 23671132 NULL 1 0 U USER_TABLE 03:10.7 03:10.7 0 0 0
COMBINEMAILING 55671246 NULL 1 0 U USER_TABLE 03:11.1 03:11.1 0 0 0
DEMOGRAPHICS 87671360 NULL 1 0 U USER_TABLE 03:11.4 03:11.4 0 0 0
*/
SELECT * FROM sys.columns
/*
has column name
object_id name column_id system_type_id user_type_id max_length precision scale collation_name is_nullable is_ansi_padded is_rowguidcol is_identity is_computed is_filestream is_replicated is_non_sql_subscribed is_merge_published is_dts_replicated is_xml_document xml_collection_id default_object_id rule_object_id is_sparse is_column_set
119671474 HONORS 10 231 231 12 0 0 SQL_Latin1_General_CP1_CI_AS 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119671474 TRANSCRIPT_DATE 11 61 61 8 23 3 NULL 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119671474 CLASS_RANK 12 56 56 4 10 0 NULL 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119671474 CLASS_SIZE 13 56 56 4 10 0 NULL 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
*/
SELECT * FROM sys.tables
/*
has table name
name object_id principal_id schema_id parent_object_id type type_desc create_date modify_date is_ms_shipped is_published is_schema_published lob_data_space_id filestream_data_space_id max_column_id_used lock_on_bulk_load uses_ansi_nulls is_replicated has_replication_filter is_merge_published is_sync_tran_subscribed has_unchecked_assembly_data text_in_row_limit large_value_types_out_of_row is_tracked_by_cdc lock_escalation lock_escalation_desc
ADDRESSSCHEDULE 7671075 NULL 1 0 U USER_TABLE 03:10.6 03:14.2 0 0 0 0 NULL 39 0 1 0 0 0 0 0 0 0 0 0 TABLE
ADVANCENAME 23671132 NULL 1 0 U USER_TABLE 03:10.7 03:10.7 0 0 0 0 NULL 18 0 1 0 0 0 0 0 0 0 0 0 TABLE
COMBINEMAILING 55671246 NULL 1 0 U USER_TABLE 03:11.1 03:11.1 0 0 0 0 NULL 16 0 1 0 0 0 0 0 0 0 0 0 TABLE
DEMOGRAPHICS 87671360 NULL 1 0 U USER_TABLE 03:11.4 03:11.4 0 0 0 0 NULL 31 0 1 0 0 0 0 0 0 0 0 0 TABLE
*/
SELECT * FROM sys.tables WHERE name LIKE '%code%'
SELECT * FROM systypes
/*
has column type
name xtype status xusertype length xprec xscale tdefault domain uid reserved collationid usertype variable allownulls type printfmt prec scale collation
text 35 0 35 16 0 0 0 0 4 0 872468488 19 0 1 35 NULL NULL NULL SQL_Latin1_General_CP1_CI_AS
uniqueidentifier 36 0 36 16 0 0 0 0 4 0 NULL 0 0 1 37 NULL 16 NULL NULL
date 40 0 40 3 10 0 0 0 4 0 NULL 0 0 1 0 NULL 10 0 NULL
time 41 0 41 5 16 7 0 0 4 0 NULL 0 0 1 0 NULL 16 7 NULL
datetime2 42 0 42 8 27 7 0 0 4 0 NULL 0 0 1 0 NULL 27 7 NULL
datetimeoffset 43 0 43 10 34 7 0 0 4 0 NULL 0 0 1 0 NULL 34 7 NULL
...
34 rows
*/
I'm using SQL Server 2008 R2
I posted on a sheet for formatting
https://docs.google.com/spreadsheets/d/1k3rubaSm0M4jXf5VKgk3DuS8QkuPwgzPZYJnsMJdQcI/edit?usp=sharing

SQL query to get Groups and sub groups hierarchy

Account table
ac_id ac_name st_id
----------- ------------- -----------
1 LIABILITES 1
2 ASSET 1
3 REVENUE 1
4 EXPENSES 1
5 EQUITY 1
Groups table
grp_id grp_name ac_no grp_of st_id type_ cmp_id
----------- ------------------- ---------- -------- --------- --------- --------
1 Capital Account 1 0 1 0 0
2 Current Liability 1 0 1 0 0
3 Loan Liability 1 0 1 0 0
4 Suspense A/C 1 0 1 0 0
5 Current Assets 2 0 1 0 0
6 Fixed Assests 2 0 1 0 0
7 Investment 2 0 1 0 0
8 Misc. Expenses 2 0 1 0 0
9 Direct Income 3 0 1 0 0
10 Indirect Income 3 0 1 0 0
11 Sale Account 3 0 1 0 0
12 Direct Expense 4 0 1 0 0
13 Indirect Expense 4 0 1 0 0
14 Purchase Account 4 0 1 0 0
15 Sundry Creditors 2 1 1 0 0
16 Sundry Debitors 5 1 1 0 0
17 Bank Account 5 1 1 0 0
18 Cash In Hand 5 1 1 0 0
19 Duties & Taxes 2 1 1 0 0
20 Salary 12 1 1 0 0
21 Personal 5 1 1 0 0
22 Loan 2 0 1 0 0
23 Customer 16 1 1 0 0
34 Vendor 15 1 1 0 0
38 Sale Softwares 11 1 1 1 1
46 Stock In Hand 5 1 1 1 1
47 test 1 1 1 1 1
48 test in 47 1 1 1 1
Query to get all groups hierarchy.
declare #ac_no as int =2
;With CTE(grp_id,grp_name,ac_no,Level)
AS
( SELECT
grp_id,grp_name,ac_no,CAST(1 AS int)
FROM
Groups
WHERE
grp_id in (select grp_id from Groups where (ac_no=#ac_no) and grp_of=0)
UNION ALL
SELECT
o.grp_id,o.grp_name,o.ac_no,c.Level+1
FROM
Groups o
INNER JOIN
CTE c
ON c.grp_id=o.ac_no --where o.ac_no=2 and o.grp_of=1
)
select * from CTE
Result is ok for ac_no=2/3/4
grp_id grp_name ac_no Level
----------- ------------------- ----------- ------
5 Current Assets 2 1
6 Fixed Assests 2 1
7 Investment 2 1
8 Misc. Expenses 2 1
22 Loan 2 1
16 Sundry Debitors 5 2
17 Bank Account 5 2
18 Cash In Hand 5 2
21 Personal 5 2
46 Stock In Hand 5 2
23 Customer 16 3
But when I try to get result for ac_no=1;
I get error :
Msg 530, Level 16, State 1, Line 4
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
I think the issue is that you end up in an infinite recursion as you have a row that is it's own parent/child (eg. grp_id = ac_no).
I think it should work if you add a limiting clause to the recursive member like this:
DECLARE #ac_no AS int = 1;
WITH CTE (grp_id , grp_name , ac_no , Level ) AS (
SELECT grp_id, grp_name, ac_no, CAST( 1 AS int )
FROM Groups
WHERE grp_id IN (SELECT grp_id FROM Groups WHERE ac_no = #ac_no AND grp_of = 0)
UNION ALL
SELECT o.grp_id, o.grp_name, o.ac_no, c.Level + 1
FROM Groups o
INNER JOIN CTE c ON c.grp_id = o.ac_no --where o.ac_no=2 and o.grp_of=1
WHERE c.ac_no <> c.grp_id
)
SELECT * FROM CTE;

Where to find the size of SQL Server data types

I am trying to calculate the size of my database. I will have a table with 3 columns (id, int, money) I will have 26 million rows with all columns being occupied. How big will my database be? Also, where can I find the size of all SQL Server data types?
Your can use below query :
SELECT * FROM sys.types
result of above query is below :
name system_type_id user_type_id schema_id principal_id max_length precision scale collation_name is_nullable is_user_defined is_assembly_type default_object_id rule_object_id is_table_type
-------------------- -------------- ------------ --------- ------------ ---------- --------- ----- ----------------- ----------- --------------- ---------------- ----------------- -------------- -------------
image 34 34 4 NULL 16 0 0 NULL 1 0 0 0 0 0
text 35 35 4 NULL 16 0 0 Persian_100_CI_AI 1 0 0 0 0 0
uniqueidentifier 36 36 4 NULL 16 0 0 NULL 1 0 0 0 0 0
date 40 40 4 NULL 3 10 0 NULL 1 0 0 0 0 0
time 41 41 4 NULL 5 16 7 NULL 1 0 0 0 0 0
datetime2 42 42 4 NULL 8 27 7 NULL 1 0 0 0 0 0
datetimeoffset 43 43 4 NULL 10 34 7 NULL 1 0 0 0 0 0
tinyint 48 48 4 NULL 1 3 0 NULL 1 0 0 0 0 0
smallint 52 52 4 NULL 2 5 0 NULL 1 0 0 0 0 0
int 56 56 4 NULL 4 10 0 NULL 1 0 0 0 0 0
smalldatetime 58 58 4 NULL 4 16 0 NULL 1 0 0 0 0 0
real 59 59 4 NULL 4 24 0 NULL 1 0 0 0 0 0
money 60 60 4 NULL 8 19 4 NULL 1 0 0 0 0 0
datetime 61 61 4 NULL 8 23 3 NULL 1 0 0 0 0 0
float 62 62 4 NULL 8 53 0 NULL 1 0 0 0 0 0
sql_variant 98 98 4 NULL 8016 0 0 NULL 1 0 0 0 0 0
ntext 99 99 4 NULL 16 0 0 Persian_100_CI_AI 1 0 0 0 0 0
bit 104 104 4 NULL 1 1 0 NULL 1 0 0 0 0 0
decimal 106 106 4 NULL 17 38 38 NULL 1 0 0 0 0 0
numeric 108 108 4 NULL 17 38 38 NULL 1 0 0 0 0 0
smallmoney 122 122 4 NULL 4 10 4 NULL 1 0 0 0 0 0
bigint 127 127 4 NULL 8 19 0 NULL 1 0 0 0 0 0
hierarchyid 240 128 4 NULL 892 0 0 NULL 1 0 1 0 0 0
geometry 240 129 4 NULL -1 0 0 NULL 1 0 1 0 0 0
geography 240 130 4 NULL -1 0 0 NULL 1 0 1 0 0 0
varbinary 165 165 4 NULL 8000 0 0 NULL 1 0 0 0 0 0
varchar 167 167 4 NULL 8000 0 0 Persian_100_CI_AI 1 0 0 0 0 0
binary 173 173 4 NULL 8000 0 0 NULL 1 0 0 0 0 0
char 175 175 4 NULL 8000 0 0 Persian_100_CI_AI 1 0 0 0 0 0
timestamp 189 189 4 NULL 8 0 0 NULL 0 0 0 0 0 0
nvarchar 231 231 4 NULL 8000 0 0 Persian_100_CI_AI 1 0 0 0 0 0
nchar 239 239 4 NULL 8000 0 0 Persian_100_CI_AI 1 0 0 0 0 0
xml 241 241 4 NULL -1 0 0 NULL 1 0 0 0 0 0
sysname 231 256 4 NULL 256 0 0 Persian_100_CI_AI 0 0 0 0 0 0
CalculatedCreditInfo 243 257 9 NULL -1 0 0 NULL 0 1 0 0 0 1
udt_QoutaDetail 243 258 21 NULL -1 0 0 NULL 0 1 0 0 0 1
BeforeUpdate 243 259 22 NULL -1 0 0 NULL 0 1 0 0 0 1
udt_StoreInventory 243 260 26 NULL -1 0 0 NULL 0 1 0 0 0 1
udt_WKFHistory 243 261 32 NULL -1 0 0 NULL 0 1 0 0 0 1
IDTable 243 262 1 NULL -1 0 0 NULL
you can use max_length for size of each data type.
T-SQL has a function for that: DATALENGTH for all SQL Server versions.
Example:
DECLARE #lat DECIMAL(10, 7) = 3.14151415141514151415;
SELECT #lat, DATALENGTH(#lat);
Result:
3.1415142 and 5 (because DECIMAL(10,7) uses 5 bytes to be stored).
Documentation: https://learn.microsoft.com/en-us/sql/t-sql/functions/datalength-transact-sql?view=sql-server-ver15
For example, I have a table called Applications with these columns: (id VARCHAR(32), debug BIT, connectionString VARCHAR(2048), firebaseKey VARCHAR(4096)). As we know, VARCHAR doesn't allocate all the space (just what you need, so 'A' is 1 byte in VARCHAR).
These queries:
SELECT
SUM(DATALENGTH(id)) AS idSize,
SUM(DATALENGTH(debug)) AS debugSize,
SUM(DATALENGTH(connectionString)) AS connectionStringSize,
SUM(DATALENGTH(firebaseKey)) AS firebaseKeySize
FROM Applications;
SELECT
SUM(
DATALENGTH(id) +
DATALENGTH(debug) +
DATALENGTH(connectionString) +
DATALENGTH(firebaseKey)
) AS totalSize
FROM Applications;
will return my data size (in my case, with my rows, is 8, 2, 366, 4698 (total: 5074). There are 2 rows in that table.
Notice that this does NOT represent the total size of my database (there are pages, descriptors, indexes, etc. involved.)*
MSSQL has internal stored procedures to tell you the exactly size of your database in disk:
EXEC sp_spaceused; for all database;
EXEC sp_spaceused N'schema.TableName'; for a specific table;
EXEC sp_helpdb N'DatabaseName'; if you want details from each file.
http://msdn.microsoft.com/en-us/library/ms187752.aspx
Money : 8 bytes
int : 4 bytes
id - depends on what you mean.
If the table specified in the where clause contains a nvarchar, this query will give you how many characters there are for that column correctly!
This detects if the column is "wide" and essentially divides by 2. More broad than just nvarchar.
SELECT c.name, (CASE WHEN LEFT(ts.name, 1) = 'n' AND ts.[precision] = 0 AND ts.[scale] = 0 THEN c.max_length / ts.[bytes] ELSE c.max_length END) AS [length]
FROM sys.columns AS c
INNER JOIN sys.tables AS t
ON t.object_id = c.object_ID
INNER JOIN
(
SELECT *, (CASE WHEN [bits] = -1 THEN -1 ELSE ([bits] + 7) / 8 END) AS [bytes]
FROM (
SELECT *, (CASE WHEN max_length >= 256 THEN (CASE WHEN LEFT(name, 1) = 'n' AND [precision] = 0 AND [scale] = 0 THEN 16 ELSE 8 END) ELSE max_length END) AS [bits]
FROM sys.types AS iits
) AS its
) AS ts
ON ts.user_type_id = c.user_type_id
WHERE t.name LIKE 'tb_tablename' -- LIKE is case insensitive
Of course, you can just divide max_length on sys.columns by 2 if you know the column is an nvarchar. This is more for discovering table schema in a way that seems better for if new sql data types are introduced in the future. And you so-choose to upgrade to it. Pretty small edge case.
Please edit and correct this answer if you find an edge case where
bytes and bits are incorrect.
Details:
-- ([bits] + 7) / 8 means round up
--
-- Proof:
-- o (1 bit + 7 = 8) / 8 = 1 byte used
-- o ((8 + 8 + 1 = 17 bytes) + 7 = 24) / 8 = 3 byes used
-- o ((8 + 8 + 7 = 23 bytes) + 7 = 30) / 8 = 3.75 = integer division removes decimal = 3
SELECT *, (CASE WHEN [bits] = -1 THEN -1 ELSE ([bits] + 7) / 8 END) AS [bytes]
FROM (
SELECT *, (CASE WHEN max_length >= 256 THEN (CASE WHEN LEFT(name, 1) = 'n' AND [precision] = 0 AND [scale] = 0 THEN 16 ELSE 8 END) ELSE max_length END) AS [bits]
FROM sys.types AS its
) AS ts
If someone knows that SQL Server stores the bit and byte sizes for each data type. Or a better way to get sys.columns size, please leave a comment!

Need help to get sql query output like this

This is my query
select
dtfromdate, dttodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate)) AS NumberOfDays,
fltspl
from dbo.tblHR_SpecialLeaveTransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
order by
dtfromdate
Result :
dtfromdate dttodate NumberOfDays fltspl
----------------------- ----------------------- ------------ ----------------------
2012-05-01 00:00:00 2012-05-31 00:00:00 30 30
Another query
select
dtfromdate, dtTodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate) ) AS NumberOfDays,
fltcl, fltsl, fltpl, fltcompoff, fltod, fltlop,
isnull(fltflexiL, 0) as fltflexiL
from
tblhr_leavetransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
order by
dtfromdate
Result:
dtfromdate dtTodate NumberOfDays fltcl fltsl fltpl fltcompoff fltod fltlop fltflexiL
----------------------- ----------------------- ------------ ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ----------------------
2011-01-14 00:00:00 2011-01-14 00:00:00 0 1 0 0 0 0 0 0
2011-01-17 00:00:00 2011-01-17 00:00:00 0 1 0 0 0 0 0 0
2011-01-25 00:00:00 2011-01-25 00:00:00 0 0 0 0 0 1 0 0
2011-04-01 00:00:00 2011-04-02 00:00:00 1 0 0 0 0 2 0 0
2011-05-14 00:00:00 2011-05-14 00:00:00 0 0 0 0 0 1 0 0
2011-05-16 00:00:00 2011-05-16 00:00:00 0 0 0 0 1 0 0 0
2011-05-18 00:00:00 2011-05-18 00:00:00 0 1 0 0 0 0 0 0
2011-05-19 00:00:00 2011-05-20 00:00:00 1 0 2 0 0 0 0 0
2011-05-21 00:00:00 2011-05-21 00:00:00 0 1 0 0 0 0 0 0
2011-05-23 00:00:00 2011-05-23 00:00:00 0 0 0 0 1 0 0 0
I need the output like this,
dtfromdate dtTodate NumberOfDays fltcl fltsl fltpl fltcompoff fltod fltlop fltflexiL fltspl
----------------------- ----------------------- ------------ ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ---------------------- ----------
2011-01-14 00:00:00 2011-01-14 00:00:00 0 1 0 0 0 0 0 0 0
2011-01-17 00:00:00 2011-01-17 00:00:00 0 1 0 0 0 0 0 0 0
2011-01-25 00:00:00 2011-01-25 00:00:00 0 0 0 0 0 1 0 0 0
2011-04-01 00:00:00 2011-04-02 00:00:00 1 0 0 0 0 2 0 0 0
2011-05-14 00:00:00 2011-05-14 00:00:00 0 0 0 0 0 1 0 0 0
2011-05-16 00:00:00 2011-05-16 00:00:00 0 0 0 0 1 0 0 0 0
2011-05-18 00:00:00 2011-05-18 00:00:00 0 1 0 0 0 0 0 0 0
2011-05-19 00:00:00 2011-05-20 00:00:00 1 0 2 0 0 0 0 0 0
2011-05-21 00:00:00 2011-05-21 00:00:00 0 1 0 0 0 0 0 0 0
2011-05-23 00:00:00 2011-05-23 00:00:00 0 0 0 0 1 0 0 0 0
2012-05-01 00:00:00 2012-05-31 00:00:00 30 0 0 0 0 0 0 0 30
Looks like you just want to union two queries together. To do this both queries must include all columns, just set those to null/zero as necessary. One other slight difficulty is that you cant use order by when unioning, unless you subselect the whole thing.
Without the order by:
select
dtfromdate, dttodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate)) AS NumberOfDays,
0 as fltcl,
0 as fltsl,
0 as fltpl,
0 as fltcompoff,
0 as fltod,
0 as fltlop,
0 as fltflexiL,
fltspl
from dbo.tblHR_SpecialLeaveTransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
union
select
dtfromdate, dtTodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate) ) AS NumberOfDays,
fltcl, fltsl, fltpl, fltcompoff, fltod, fltlop,
isnull(fltflexiL, 0) as fltflexiL ,
0 as fltspl
from
tblhr_leavetransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
If you need a specific order:
SELECT * FROM
(
select
dtfromdate, dttodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate)) AS NumberOfDays,
0 as fltcl,
0 as fltsl,
0 as fltpl,
0 as fltcompoff,
0 as fltod,
0 as fltlop,
0 as fltflexiL,
fltspl
from dbo.tblHR_SpecialLeaveTransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
union
select
dtfromdate, dtTodate,
(SELECT DATEDIFF(day, dtfromdate, dtTodate) ) AS NumberOfDays,
fltcl, fltsl, fltpl, fltcompoff, fltod, fltlop,
isnull(fltflexiL, 0) as fltflexiL ,
0 as fltspl
from
tblhr_leavetransaction
where
nvrempcode = 'MCL1218' and nvrstatus = 1
) src
order by dtfromdate

Resources