How to get the result of CONNECT_BY_ISCYCLE and CONNECT_BY_ISLEAF in snowflake without using them? - snowflake-cloud-data-platform

I need to make hierarchical queries, and I need to get the results of CONNECT_BY_ISCYCLE and CONNECT_BY_ISLEAF, but these features are supported in Oracle not in Snowflake.
What are the alternative ways to implement the functionalities of CONNECT_BY_ISCYCLE and CONNECT_BY_ISLEAF in snowflake without using them as these keywords are not supported there?

Wonder if you have taken a look at the following Snowflake features?
https://docs.snowflake.net/manuals/user-guide/queries-hierarchical.html#using-connect-by-or-recursive-ctes-to-query-hierarchical-data

Yes I took a look there. I also took a look at https://docs.snowflake.net/manuals/sql-reference/constructs/connect-by.html where it clearly says that these features are not supported in Snowflake.
I was trying below code block to find an alternative but facing varieties of error in snowflake.
person_vertex as (
select
emp_number,
user_id
from person
),
person_edges as (
select
supervisor_emp_number,
emp_number
from person
where supervisor_emp_number is not null
),
select
pv.emp_number emp_id_pk,
level,
CONNECT_BY_ROOT pv.emp_number AS root,
concat(SYS_CONNECT_BY_PATH(pv.emp_number,':'),':') as path,
-- CONNECT_BY_ISCYCLE AS iscyclic, ------------------- no idea how to implement this
-- CONNECT_BY_ISLEAF as isleaf ------------------- i tried below block, but it is not working
case
when (pe.supervisor_emp_number in (select emp_number from pv)) then 0
else 1
end AS isleaf
from person_vertex pv
left join person_edges pe on pv.emp_number = pe.emp_number
connect by prior A.emp_number = A.supervisor_emp_number
start with A.supervisor_emp_number is null
Any help with this block is really appreciated.
Thanks.
enter code here

Related

Why Hibernate HSQL Concat is not working for MSSQL?

So, I have Hibernate 5.3.1 in a project which connects to different enginees (MySql, Oracle, PostgreSQL and MS SQL), so I can't use native queries.
Let's say I have 3 records in a table, which all of them have the same datetime, but I need to group them only by date (not time). For example, 2019-12-04;
I execute this query:
SELECT
CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)),
iss.code,
COUNT(tx.id)
FROM
tx_ tx
JOIN
issuer_ iss
ON
tx.id_issuer = iss.id
GROUP BY
CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)), iss.code
But, when I test it connected to SQL SERVER 2017, instead of return 20191204, it's returning 2035. In Oracle and MySQL is working fine.
Anyone has any idea why is this happen? I've tried different ways, like use + instead of CONCAT but the result is the same.
I've also tried to extract them for separate (without concat), and they have been returning correct. The problem is, I need to group them by the complete date.
And just for the record, the field is declared as datetime2 in DDBB
How about simply adding them, instead of using CONCAT.
(year(tx.date_)*10000 + month(tx.date_)*100 + day(tx.date_)*1) AS datenum
Thus, try this:
SELECT
CAST((year(tx.date_)*10000 + month(tx.date_)*100 + day(tx.date_)*1) AS string) AS datenum,
iss.code
FROM tx_ tx
JOIN issuer_ iss
ON tx.id_issuer = iss.id
GROUP BY year(tx.date_), month(tx.date_), day(tx.date_), iss.code
Thanks for the hint Gert Arnold gave me. I just didn't realize that the query was adding like if they were numbers in MSSQL.
Finally, I manage to make it work in the 4 RDBMS casting to string first
SELECT
CONCAT(CAST(year(tx.date_) AS string), CAST(month(tx.date_) AS string), CAST(day(tx.date_) AS string)),
iss.code
FROM
tx_ tx
JOIN
issuer_ iss
ON
tx.id_issuer = iss.id
GROUP BY
CONCAT(year(tx.date_), month(tx.date_), day(tx.date_)), iss.code
I tried also casting to TEXT, but it throws exception in MySQL
Why use concat() to begin with?
Assuming Hibernate takes care of converting the non-standard year(), month() and day() functions, then the following should work on any DBMS
SELECT year(tx.date_), month(tx.date_), day(tx.date_), iss.code
FROM tx_ tx
JOIN issuer_ iss ON tx.id_issuer = iss.id
GROUP BY year(tx.date_), month(tx.date_), day(tx.date_), iss.code

MS Access query making sure Higher retails match

I'm trying to build a query in MS Access and having an issue figuring out the best way to build it. What I'm trying to do is is make sure all the Higher retails match within a set of matching pack numbers. For example:
PackNum Prefix Retail
6451618 DF 37.99
6451618 SK 37.99
6451618 VJ 34.99
6451618 SG 37.99
One of the group is off and I want the query to show it.
I was attempting to use something like this to have check but I'm not getting the results I'm looking for
IIf([dbo_PIC704Current]![PackNum]=[dbo_PIC704Current]![PackNum]
And [dbo_PIC704Current]![Ret2]<>[dbo_PIC704Current]![Ret2],True,False)
Any help or push in the right direction would be greatly appreciated!
-Deke
SELECT dbo_pic704current.packnum
, Min(dbo_pic704current.Ret2) AS LowRet2
, Max(dbo_pic704current.Ret2) AS HighRet2
, dbo_CatalogInfo.MediaId
, dbo_pic704current.DiscountReasonCode
, dbo_CatalogInfo.Brand
FROM dbo_pic704current INNER JOIN dbo_CatalogInfo ON (dbo_pic704current.year =
dbo_CatalogInfo.mailyear) AND (dbo_pic704current.catid = dbo_CatalogInfo.catalog)
WHERE (((dbo_CatalogInfo.MediaId)='CAT Catalog'))
GROUP BY dbo_pic704current.packnum, dbo_CatalogInfo.MediaId,
dbo_pic704current.DiscountReasonCode, dbo_CatalogInfo.Brand, dbo_pic704current.Year
HAVING (((Min(dbo_pic704current.Ret2))<>Max([Ret2])))
ORDER BY dbo_pic704current.packnum;
Your existing solution using aggregation is likely to yield better performance, but to offer an alternative, here is an example using a correlated subquery:
select
pc.packnum, pc.ret2, ci.mediaid, pc.discountreasoncode, ci.brand
from
dbo_pic704current pc inner join dbo_cataloginfo ci on
pc.year = ci.mailyear and pc.catid = ci.catalog
where
ci.mediaid = 'cat catalog' and exists
(select 1 from dbo_pic704current t where t.packnum = pc.packnum and t.ret2 > pc.ret2)
order by
pc.packnum

How to find rows in ms-sql with another rows' value followingly?

I have created an Sql table to trace objects' operation history. I have two columns; first one is the self tracing code and second tracing code is the tracing code for the code coming from source object to target. I created this to be able to look up the route of operations through the objects. You can see the tracing sample table below:
I need to create an sql code to query to show all the route in one table. When I first select the self code, it will be the incoming code for previous rows. There may be more than one incoming code to self and I want to be able to trace all. And I want to reach end until my search is null.
I tried select query like below but I am so new sql and need your help.
SELECT [TracingCode.Self],
[TracingCode.Incoming],
[EquipmentNo]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = (SELECT [TracingCode.Incoming]
FROM [MKP_PROCESS_PRODUCT_REPORTS].[dbo].[ProductionTracing.Main]
WHERE [TracingCode.Self] = '028.001.19.2.3')));
To do this kind of parent/child thing to any level without explicitly coding all levels you need to use a recursive CTE.
More details here
https://www.red-gate.com/simple-talk/sql/t-sql-programming/sql-server-cte-basics/
Here is some test data and a solution I came up with. Note that three records actually match 028.001.19.2.3
If this doesn't do what you need please explain further with sample data.
DECLARE #Sample TABLE (
TC_Self CHAR(14) NOT NULL,
TC_In CHAR(14) NOT NULL,
EquipmentNo INT NOT NULL
);
INSERT INTO #Sample (TC_Self, TC_In, EquipmentNo)
VALUES
('028.001.19.2.3','026.003.19.2.2',96),
('028.001.19.2.3','026.001.19.2.2',96),
('028.001.19.2.3','026.002.19.2.2',96),
('028.001.19.2.2','026.002.19.2.1',96),
('028.001.19.2.2','026.002.19.2.1',96),
('028.001.19.2.1','026.002.19.1.1',96),
('026.003.19.2.2','024.501.19.2.5',117),
('024.501.19.2.5','024.501.19.2.6',999),
('024.501.19.2.6','024.501.19.2.7',998);
WITH CTE (RecordType, TC_Self, TC_In, EquipmentNo)
AS
(
-- This is the 'root'
SELECT 'Root' RecordType, TC_Self, TC_In, EquipmentNo FROM #Sample
WHERE TC_Self = '028.001.19.2.3'
UNION ALL
SELECT 'Leaf' RecordType, S.TC_Self, S.TC_In, S.EquipmentNo FROM #Sample S
INNER JOIN CTE
ON S.TC_Self = CTE.TC_In
)
SELECT * FROM CTE;
Also please note that most of the time to generate this answer was taken in generating the sample data to use.
In future when asking questions, people are far more likely to help if you post this sample data generation yourself

SQL Server: IsMSShipped = 0 but system SPs still returned

SELECT DISTINCT
OBJECT_SCHEMA_NAME (sc.object_id) as "schema", OBJECT_NAME(sc.object_id) as "name", sc.*
-- FROM syscomments sc
FROM sys.sql_modules sc
WHERE "Definition" LIKE '%raiserror%'
and
OBJECTPROPERTY(object_id, 'IsMSShipped') = 0
and
OBJECT_NAME(sc.object_id) like '%diagram%'
Why is this query returning these SPs? Aren't they from Microsoft?
sp_helpdiagramdefinition
sp_creatediagram
sp_renamediagram
sp_alterdiagram
sp_dropdiagram
IsMSShipped is set to 1 for any object that was created during SQL Server's installation. The Diagram objects are optional and are only added to a database after the initial installation.
In other words, although they are from MS, they are not Shipped from MS (at least not as MS is defining "Shipped").
Yes I know, it's dumb, everyone gets tripped up by this at least once. They should have called it something like IsMSInstalled instead. Just goes to show the importance of picking good names.
The SOP way to handle this is to also filter on the schema ("sys" is always schema_id 4).

How to find misspellings in data

I am trying to find the misspellings in TOWN_C field. Data looks something like below. There is no specific pattern, sometimes misspelling can be at the beginning, sometimes it can be in middle or at the end. Length of misspelling can be different too.
I am using SQL Server Management Studio to execute the queries. I used SUBSTR to find out duplicates along with the left outer join. But that does not give only misspelling. I still need to go and manually look at data.
Data ->
Achampet
ACHEMPET
AGIA
AGIYA
ASHOK NAGAR
ASHOKNAGAR
ASHOKNAGER
SQL query which I am using ->
Select distinct(T3.TOWN__C)
From (Select T1.Sub_Str, Count(T1.Sub_Str) as Y
From (SELECT TOWN__C, SUBSTRING(TOWN__C, 1, 3) as Sub_Str
FROM [SALESFORCE].[dbo].[Outlet Master] group by TOWN__C)T1
Group by T1.Sub_Str having count(*)> 1)T2
Left outer join
[SALESFORCE].[dbo].[Outlet Master]T3
On T2.Sub_Str = SUBSTRING(T3.TOWN__C, 1, 3)
Order by T3.TOWN__C
Is there a way to find out all such cases using SQL or Excel or anything else?
Here's an example using SOUNDEX, to try to locate values where multiple spellings have been used for "similar" names:
declare #t table (town varchar(35) not null)
insert into #t(town) values
('Achampet'),
('ACHEMPET'),
('AGIA'),
('AGIYA'),
('ASHOK NAGAR'),
('ASHOKNAGAR'),
('ASHOKNAGER'),
('Downtown'),
('DOWNTOWN'),
('DownTown')
select
v.*
from
(select
*,
MIN(town) OVER (PARTITION BY town_sound) as minTown,
MAX(town) OVER (PARTITION BY town_sound) as maxTown
from
#t
cross apply
(select SOUNDEX(REPLACE(town,' ','')) as town_sound) u
) v
where minTown != maxTown
Note that this doesn't return "downtown" where the only variations are in capitalization, but does return all of the values in your given sample data, which I assume were all meant to be found as possible misspellings.
Also note that SOUNDEX has had a chequered history and under older versions of SQL Server it was usually recommended that a "better" soundex be implemented as a UDF. You should be able to find versions of that with a simple search, if required.
Note, also, that Soundex was specifically designed around English pronunciation. Again, you may be able to find a better tailored function as a UDF for specific other languages.
Results:
town town_sound minTown maxTown
------------- ---------- ------------- ------------
AGIA A200 AGIA AGIYA
AGIYA A200 AGIA AGIYA
ASHOK NAGAR A225 ASHOK NAGAR ASHOKNAGER
ASHOKNAGAR A225 ASHOK NAGAR ASHOKNAGER
ASHOKNAGER A225 ASHOK NAGAR ASHOKNAGER
Achampet A251 Achampet ACHEMPET
ACHEMPET A251 Achampet ACHEMPET

Resources