[{"content":"Why no longer MSSQL?\nIt has been years since last post on the MSSQL topic and now MSSQL is under the customer\u0026rsquo;s care instead of mine. The job scope has changed significantly since 2022 where the focus was shifted to Genesys Cloud (and Genesys Engage).\nWhy Genesys?\nFor me, it is considered as a new challenge which addresses the questions from the previous role where Genesys platform was deployed. How can we build a Contact Center with multiple channels such as call, email, chat, social media and instant message? What about integration with CRM or other system used by contact center users? What are the options to improve efficiency? Looking back the past 4 years, some of the questions were already answered, and some deviate from the original ones, especially after the AI has entered the chat.\nOne thing remains though. The knowledge sharing article will be updated regularly along with the Genesys journey where I am grateful to be taught by multiple mentors across all the regions. One Genesys is truly One Genesys.\n","date":"2026-10-05T00:00:00Z","image":"https://www.tranhaidang.com/2026/10/05/new-chapter-with-genesys/Genesys_huc15ea1c752372869666379c978a9c38d_35610_120x120_fill_box_smart1_3.png","permalink":"https://www.tranhaidang.com/2026/10/05/new-chapter-with-genesys/","title":"New Chapter with Genesys"},{"content":"For this blog, let\u0026rsquo;s wear the Developer DBA hat and discuss how we can use T-SQL to transpose columns to rows using PIVOT and UNPTVOT operator (for MSSQL 2012 and newer).\nTo be more specific, assuming that we got the end result of ETL process with various Stats with their datetime info as following\nOriginal data whereas each row represents 1 day of various stats for the day. And then on one beautiful day your boss wanna review the result as something like below due to the water-fall dependency of those stats e.g. Stat3 = Stat4 + Stat5 etc.\nEnd Result While Excel can accomplish this request easily, we are database professional and willing to take the challenge to tackle this issue using T-SQL, aren\u0026rsquo;t we?\nWhat will be the T-SQL query then?\nYou can refer to the answer using CTE + PIVOT + UNPIVOT below (pardon the misalignment, I am still figuring out how to make it what-you-type-is-what-you-see)\nWITH HD_CTE AS ( SELECT Timekey,[Stats], [Value] FROM [HD1].[dbo].[tblStat] UNPIVOT ( [Value] FOR [Stats] IN ( [Stat1] ,[Stat2] ,[Stat3] ,[Stat4] ,[Stat5] ,[Stat6] ,[Stat7] ,[Stat8] ,[Stat9] )) AS U ) SELECT Stats, [20220201],[20220202],[20220203], [20220204], [20220205], [20220206], [20220207],[20220208],[20220209], [20220210], [20220211],[20220212],[20220213], [20220214], [20220215], [20220216], [20220217],[20220218],[20220219], [20220220], [20220221],[20220222],[20220223], [20220224], [20220225], [20220226], [20220227],[20220228] FROM HD_CTE PIVOT (SUM(VALUE) FOR Timekey IN ( [20220201],[20220202],[20220203], [20220204], [20220205], [20220206], [20220207],[20220208],[20220209], [20220210], [20220211],[20220212],[20220213], [20220214], [20220215], [20220216], [20220217],[20220218],[20220219], [20220220], [20220221],[20220222],[20220223], [20220224], [20220225], [20220226], [20220227],[20220228]\t) ) AS P ORDER BY Stats 1 area of improvement can be the dynamic population of YYYYMMDD based on the input parameter of month and year.\nUsing Python instead of T-SQL\nThere is a saying \u0026lsquo;There are more than one way to skin a cat\u0026rsquo; whereas we can use Python and leverage on the pandas library since it allows a single DataFrame function (.T) to accomplish the same result with the lengthy T-SQL script above. Full code can be found below\nimport pyodbc import pandas as pd # Reading the data from SQL Server con = pyodbc.connect(\u0026#39;DRIVER={ODBC Driver 17 for SQL Server};SERVER=localhost;DATABASE=HD1;UID=apps_login;PWD=apps_login\u0026#39;) query = \u0026#34;\u0026#34;\u0026#34; SELECT [Timekey] ,[Stat1] ,[Stat2] ,[Stat3] ,[Stat4] ,[Stat5] ,[Stat6] ,[Stat7] ,[Stat8] ,[Stat9] FROM [HD1].[dbo].[tblStat] WHERE [Timekey] LIKE \u0026#39;202202%\u0026#39; \u0026#34;\u0026#34;\u0026#34; TM = pd.read_sql(query, con) # Transpose the original DataFrame TM into to TM_transposed TM_transposed = TM.T TM_transposed Hoping you like this blog post and feel free to share any comments/feedbacks below.\nThank you for your time.\n","date":"2022-02-26T00:00:00Z","image":"https://www.tranhaidang.com/2022/02/26/tranpose-data-using-t-sql-and-python/bg_Transpose_hu6ee29dd1582045e2856e0e96d01d85ad_60017_120x120_fill_q75_box_smart1.jpg","permalink":"https://www.tranhaidang.com/2022/02/26/tranpose-data-using-t-sql-and-python/","title":"Tranpose data using T-SQL and Python"},{"content":"Why would you do this?\nAs one of the responsibilities for Production DBA role, we would need to ensure that data is backup properly before the disaster strikes. And you wouldn\u0026rsquo;t know when that thing happens, be it the corrupted data pages, certain developers or even your DBA team members make any mistakes unintentionally/intentionally.\nBacking up data is just half of the process, you might want to verify whether you can restore the DB using that backup data. It is fair to say that only when the restoration is successful without any error, the data that you back up is in good shape.\nHigh level of backup process\nThe assumption is that there are 2 instances e.g, Production and DR/Testing instance with a shared folder in the network where it stores the precious backup data as per diagram below\nBackup Process The OS of DR/Testing instance is Windows 2012/2016.\nUpload backup\nI am using the backup script from Ola Hallengren to do the back up from the PROD instance to a shared folder in the network. There are tons of options for you to consider and customize the backup process. Typically, @Verify, @Compress, @CheckSum are the useful paramters and @Directory will be the shared folder.\nAs a common practice, a complete backup = Full + Differential + Log backup\nFULL\nEXECUTE dbo.DatabaseBackup @Databases = 'USER_DATABASES', @Directory = '\\\\ShareFolder\\PRODinstance\\Backup', @BackupType = 'FULL', @Compress = 'Y', @CheckSum = 'Y' DIFFERENTIAL\nEXECUTE dbo.DatabaseBackup @Databases = 'USER_DATABASES', @Directory = '\\\\ShareFolder\\PRODinstance\\Backup', @BackupType = 'DIFF', @Compress = 'Y', @CheckSum = 'Y' LOG\nEXECUTE dbo.DatabaseBackup @Databases = 'USER_DATABASES', @Directory = '\\\\ShareFolder\\PRODinstance\\Backup', @BackupType = 'LOG', @Compress = 'Y', @CheckSum = 'Y' Download backup\nYou would need a simple script e.g. xcopy to copy the backups from shared folder to the server hosting the DR/Testing instance and running it under Task Scheduler\nxcopy \u0026quot;\\\\SharedFolder\\PRODinstance\\Backup\u0026quot; \u0026quot;E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\u0026quot;\nFor example, we got the following backup files with mixture of FULL + DIFF + LOG E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_FULL_20220219_023000.bak E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_DIFF_20220220_023000.bak E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_DIFF_20220221_023000.bak E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_LOG_20220221_033000.trn E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_LOG_20220221_043000.trn E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_LOG_20220221_053000.trn E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_LOG_20220221_063000.trn E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\HaiDangSQL\\ReportDatabase\\FULL\\HaiDangSQL_ReportDatabase_LOG_20220221_073000.trn\nThere will be 3 steps to restore those backups automatically\nCreate the restoration stored procedure Admin_RestoreDatabases_Daily under a datbased used by SQL Admin team. (e.g. AdminDB). There are 5 parameters with their name indicating the purpose @serverName @databaseName @backupPath @dataFilePath @logFilePath Create a SQL agent job with 2 steps calling to the stored procedure above to restore the database to \u0026lsquo;G:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Data' (@dataFilePath) and \u0026lsquo;H:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Data' (@logFilePath). The stored procedure will restore in the order of the FULL, followed by the latest DIFF then those LOG later than the latest DIFF. Step 1:\nGO ALTER DATABASE ReportDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE; GO USE AdminDB; GO exec dbo.Admin_RestoreDatabases_Daily \u0026#39;HaiDangSQL\u0026#39;,\u0026#39;ReportDatabase\u0026#39;, \u0026#39;E:\\MSSQL15.MSSQLSERVER\\MSSQL\\Backup\\\u0026#39;, \u0026#39;G:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Data\\\u0026#39;, \u0026#39;H:\\Program Files\\Microsoft SQL Server\\MSSQL15.MSSQLSERVER\\MSSQL\\Data\\\u0026#39;; GO ALTER DATABASE ReportDatabase SET MULTI_USER; Step 2: Link the \u0026lsquo;apps_login\u0026rsquo; user in this ReportDatabase to the existing \u0026lsquo;apps_login\u0026rsquo; login in the DR/Testing instance. You might need to create this login before doing this step 2 if required.\nUSE ReportDatabase exec sp_change_users_login \u0026#39;Update_One\u0026#39;, \u0026#39;apps_login\u0026#39;, \u0026#39;apps_login\u0026#39;; GO Configure the SQL agent job schedule e.g. Daily @ 4.00 AM and alert in the event either of Step 1 or 2 above fails. The task is completed!\nLast but not least, a gentle reminder not to query the data in this DR/Testing instance unless you have it covered by a proper license.\nHoping you like this article and feel free to share any comments/feedbacks below.\nThank you for your time.\n","date":"2022-02-20T00:00:00Z","image":"https://www.tranhaidang.com/2022/02/20/verifying-backup-as-part-of-the-dr-strategy/bg_VerifyingBackup_huf55d9c4b1a0dc8198c86703cd19465b5_181721_120x120_fill_q75_box_smart1.jpg","permalink":"https://www.tranhaidang.com/2022/02/20/verifying-backup-as-part-of-the-dr-strategy/","title":"Verifying backup as part of the DR strategy"},{"content":"This blog will continue the previous topic of the MSSQL 2019 Standard Edition for PROD and DR site. It however would cover the PROD site setup only for limited buget project. Hence, it assumes that you need to build the whole PROD site from the scratch and only focuses on the setup with the most minimal equipment involved e.g., SAS connection rather than FC/iSCSI and would use HPE equipment e.g. servers and SAN as the sample. For other hardware vendors, you might consult the local distributor of the respective ones.\nAs of Dec 2021, the following components can be used for this setup\n2 x DL360 Gen10 with HPE Smart Array E208e-p as HBA Adapter 1 x HPE MSA 2040 12Gb SAS SFF Storage. It is recommended to check with the local distributor for the compatibility of the equipment e.g., HBA, server and SAN.\nWhile servers and SAN path (SAS cables) are catered with multiple units, SAN is still the single point of failure as there is only 1 unit without redundancy. However, it is worth to mention that there are 2 Active-Active controllers for that HPE MSA and we also got a standby MSSQL failover instance on the DR site. It is again targeted for limited budget project which still requires redundancy.\nFew tips on the hardware selection for MSSQL 2019 Standard\nDL360 G10 CPU: Choose 2 x the highest CPU speed with 12 cores e.g., Intel Gold 6256 (3.6 GHz) if you plan to fully utilize the number of CPU cores (24 cores) supported by MSSQL 2019 Standard. If you purchase lesser licenses for CPU cores, you might need to adjust the CPU cores accordingly. RAM: at least 160 GB (128 GB for Database Engine and 32 GB for OS). If other components of MSSQL e.g., Integration Service, Reporting Service etc. are installed into the server, you would need to cater additional RAM for them. Refer to MSSQL 2019 features supported for more info. HDD: Including NVMe SSD for TempDB is highly recommended. Add on OS and/or MSSQL if the budget allows. HPE MSA While there is a trend using Consumer SSD class e.g., Crucial, Samsung, ADATA as the customized SSD drives in the servers/storage product instead of paying the hefty cost of Enterprise SSD class, I would still prefer to use those drives supported by the HPE due to the hardware support and wouldn’t like going down the road of being rejected of compatibility issue. Do your research and check with the hardware vendor carefully before deciding on this. Feel free to leave your comments below.\nThank you for your time.\n","date":"2021-12-25T00:00:00Z","image":"https://www.tranhaidang.com/2021/12/25/sql2019-prod-design/bg_2b1_hu17704d3513b574de235419db260b5c96_482379_120x120_fill_q75_box_smart1.jpg","permalink":"https://www.tranhaidang.com/2021/12/25/sql2019-prod-design/","title":"MSSQL 2019 Standard Edition - Failover clustering for on-premise PROD site"},{"content":"Why MSSQL 2019?\nWhile MSSQL 2022 is around the corner, majority of the existing instances are still running MSSQL 2019 and earlier. More importantly, there is a cool feature offered by MSSQL 2019 license and it is worth to mention here\nThe MSSQL 2019 licenses allows up 2 passive failover servers for 1 PROD instance. This is considered a major change compared to MSSQL 2017 licensing and earlier version whereas you need to pay extra licenses for the 2nd passive failover server. Software Assurance (SA) of MSSQL 2019 is still required to support the failover setup You can also deploy this setup (2 failover servers) on MSSQL 2017 and earlier as long as you purchase MSSQL 2019 + SA You shouldn\u0026rsquo;t run any data manipulation transactions on the databases on the 2nd passive failover server. If you do so, it is require to pay extra licenses for this server. Only maintenance-related operations Backup, Restore, DBCC e.g. are allowed. Why Standard Edition?\nBecause it is meant for limited budget project. As of Dec 2021, Standard Edition: 3,586 USD/2cores vs Enterprise Edition: 13,748 USD/2cores\nWhy on-premise ?\nWhile cloud is becoming the major force for the IT infrastructure, there are still lots of companies prefer on-premise due to the cost, internal requirement or complete control of the infrastructure\nOut of scope\nThis article breifly explains the high-level design and won\u0026rsquo;t discuss the virtualization and the details of equipment spec and redudancy e.g. multiple links for WAN network, multiple paths from Server to SAN, multiple SAN devices/SAN switch devices as it generally depends on the hardware provider, not MSSQL.\nHigh-level design\nAdvantages of the design\nIt can survive the disater strike on individual server and also the site. If both sites are down then it is another story :P In the event either Server1A/1B is not avai, apps won\u0026rsquo;t need to be reconfigured to point to MSSQL instance. Maximizing the benefit of MSSQL 2019 licensing by minizing the number of license required, for example, assuming that Server1A/1B/2 are having same number of CPU cores, you just need to buy enough core licenses for either server. Disadvantages of the design\nIn the event PROD site is not avai, apps would need to be reconfigured to point to MSSQL instance on Server 2 manually by PROD DBA / DNS system admin. Compared to MSSQL AlwaysOn solution on Standard Edition whereas it is auto failover to Server 2, this design is not that operational transparent and might introduce downtime depending on how fast the PROD DBA / DNS system admin reacts. However, AlwaysOn on Standard Edition will also carry extra complications e.g only support 1 database.\nThe Cost for Per-Code model\nAssuming each server 1A/1B/2 are equipped with 24 cores (\u0026lt;4 sockets) to maximize the CPU cores supported by Standard Edition, the total cost for MSSQL licenses is around 51,638.4 USD with the breakdown below\nEstimated MSSQL: 12 x 3,586 = 43,032 USD Estimated SA (20% of MSSQL cost above): 12 x 3,586 x 20% = 8,606.4 USD In my experience, the actual cost is lower due to the discount offered by the local distributor, especially when they are closing on the quarter figure.\nFor the Server+CAL model, it is not popular and more suitable for the system with small limted number of users. Therefore, the cost won\u0026rsquo;t be covered in this article.\nFeel free to share any comments/feedbacks below.\nThank you for your time.\n","date":"2021-12-01T00:00:00Z","image":"https://www.tranhaidang.com/img/bg_2a.jpg","permalink":"https://www.tranhaidang.com/2021/12/01/sql2019-ha-and-dr-design/","title":"MSSQL 2019 Standard Edition - Failover clustering and DR design for on-premise system"}]