Converting an Access Query to SQL Server - sql

I am trying to convert this query to a SQL Server view
SELECT
IIF([tblStockMovementsDate] ! [LocationType] = 3, [tblShops] ! [Type], [tblLocationType] ! [LocationTypeDesc]) AS [LocationTypeDesc],
tblStockMovementsDate.[Location],
qryAllLocations.[WarehouseName],
SUM (([tblStockMovementsdate] ! [MovementQtyHangers] + ([tblStockMovementsdate] ! [MovementQtyBoxes] * Iif(Isnull([qryGarmentsPerBox] ! [GarmentsPerBox]), 1, [qryGarmentsPerBox] ! [GarmentsPerBox]))) * [qryUnitPrice] ! [UnitPrice]) AS [TotalValue],
IIF ([tblShops] ! [Type] = 'Concession', 4, [tblStockMovementsDate] ! [LocationType]) AS [LocationType]
FROM
(((((tblStockMovementsDate
INNER JOIN
tblLocationType ON tblStockMovementsDate.[LocationType] = tblLocationType.[LocationType])
INNER JOIN
qryAllLocations ON tblStockMovementsDate.[Location] = qryAllLocations.[WarehouseRef])
LEFT JOIN
qryGarmentsPerBox ON (tblStockMovementsDate.[Location] = qryGarmentsPerBox.[WarehouseRef])
AND (tblStockMovementsDate.[StockCode] = qryGarmentsPerBox.[StockCode]))
LEFT JOIN
qryUnitPrice ON tblStockMovementsDate.[StockCode] = qryUnitPrice.[StockCode])
LEFT JOIN
tblShops ON tblStockMovementsDate.[Location] = tblShops.[ShopRef])
INNER JOIN
tblStock ON tblStockMovementsDate.[StockCode] = tblStock.[StockCode]
WHERE
((IIF ([tblShops].[Clearance] = 0, [tblStock].[DeadCode] = 0, [tblStock].[RemoveFromClearance] = 0) ) <> False)
GROUP BY
IIF ([tblStockMovementsDate] ! [LocationType] = 3, [tblShops] ! [Type], [tblLocationType] ! [LocationTypeDesc]),
tblStockMovementsDate.[Location],
qryAllLocations.[WarehouseName],
IIF ([tblShops] ! [Type] = 'Concession', 4, [tblStockMovementsDate] ! [LocationType])
ORDER BY
IIF ([tblShops] ! [Type] = 'Concession', 4, [tblStockMovementsDate] ! [LocationType])
but it won't produce an output, instead I keep getting this error:
Error in list of function arguments: '=' not recognized.
Error in list of function arguments: 'IS' not recognized.
Unable to parse query text.
Any help would be appreciated.

This is a shot in the dark. I did my best to decipher the code you posted originally.
I would recommend getting rid of those nested views. They are going to cause you serious anguish at some point. You will likely have to grab the queries from those views and move that to this query.
Notice how much cleaner this is when you use aliases instead of the Access default of slapping the table in front of every column. I also removed dozens of parenthesis groups that did nothing but make this hard to see. I also converted all your IIF expressions to case expressions since I don't know what version of sql you are using.
SELECT
case when smd.LocationType = 3
then tblShops.Type
else lt.LocationTypeDesc
end AS LocTypeDesc
, smd.Location
, al.WarehouseName
, Sum((smd.MovementQtyHangers + (smd.MovementQtyBoxes * Isnull(g.GarmentsPerBox, 1))) * qryUnitPrice.UnitPrice) AS TotalValue
, case when sh.Type = 'Concession'
then 4
else smd.LocationType
end AS LocType
FROM tblStockMovementsDate smd
INNER JOIN tblLocationType lt ON smd.LocationType = ll.LocationType
INNER JOIN qryAllLocations al ON smd.Location = al.WarehouseRef
LEFT JOIN qryGarmentsPerBox g ON smd.Location = g.WarehouseRef
AND smd.StockCode = g.StockCode
LEFT JOIN qryUnitPrice up ON smd.StockCode = up.StockCode
LEFT JOIN tblShops sh ON smd.Location = sh.ShopRef
INNER JOIN tblStock st ON smd.StockCode = st.StockCode
WHERE tblShops.Clearance <> 0
OR tblStock.DeadCode <> 0
OR tblStock.RemoveFromClearance <> 0
GROUP BY case when smd.LocationType = 3 then tblShops.Type else lt.LocationTypeDesc end
, smd.Location
, al.WarehouseName
, case when sh.Type = 'Concession' then 4 else smd.LocationType end
order by LocType

Related

Add substring to an Inner Join

I want to replicate this query in my Power BI:
SELECT n.codigonotario,
n.nombrenotario,
CASE SUBSTRING(dc.path, 11, 4)WHEN '0001' THEN COUNT(cp.indiceunico)END AS NUM_OPERACIONES,
CASE SUBSTRING(dc.path, 11, 4)WHEN '0001' THEN SUM(cp.bases)END AS NUM_BASES,
SUM(dc.valornumerico / (CASE ISNULL(p.MONEDA, 0)WHEN 0 THEN 166.386 ELSE 1 END)) AS TotalCuantias,
RTRIM(LTRIM(cp.indiceunico)) AS codigoconcepto,
cp.textoconcepto + ' (' + RTRIM(LTRIM(cp.indiceunico)) + ')' AS DESCRIPCIONCONCEPTO,
cdc.categoriacampo
FROM notarios n
INNER JOIN protocolos p ON n.codigonotario = SUBSTRING(p.codigoprotocolo, 2, LEN(n.codigonotario))
INNER JOIN conceptosprotocolos cp ON cp.codigoprotocolo = p.codigoprotocolo
INNER JOIN datosconceptos dc ON dc.codigoprotocolo = p.codigoprotocolo
AND SUBSTRING(cp.path, 6, 4) = SUBSTRING(dc.path, 6, 4)
INNER JOIN camposdatosconceptos cdc ON cdc.codigocampodatos = dc.codigocampodatos
INNER JOIN conceptos c ON c.codigoconcepto = cp.codigoconcepto
WHERE p.fechaprotocolo >= '01/01/2022'
AND p.fechaprotocolo <= '31/12/2022'
AND n.codigonotario LIKE CASE LEN('Prueba')WHEN 0 THEN '%' ELSE 'Prueba' END
AND (cdc.categoriacampo = 'CUANTIA'
OR cdc.categoriacampo = 'HONORARIOSBRUTO'
OR cdc.categoriacampo = 'HONORARIOSREDUCCION')
AND p.encargado LIKE CASE LEN('Prueba')WHEN 0 THEN '%' ELSE 'Prueba' END
AND (p.codigoprotocolo LIKE 'p%'
OR p.codigoprotocolo LIKE 'c%')
AND cp.indiceunico LIKE CASE LEN(1)WHEN 0 THEN '%' ELSE 1 END
GROUP BY n.codigonotario,
n.nombrenotario,
cp.indiceunico,
cp.textoconcepto,
dc.path,
cdc.categoriacampo;
I already have the database and tables imported in my project:
And I know how to implement inner joins:
But some of those inner joins need substrings and other functions, starting with the first inner join:
INNER JOIN protocolos p ON n.codigonotario = SUBSTRING(p.codigoprotocolo, 2, LEN(n.codigonotario))
You can't use SQL functions in Power BI, but you can use Power Query, so I'm struggling trying to replicate those here (it doesn't recognize 'MID' or 'LEFT').
let
Origen = Sql.Databases("LAPTOP-OSCAR"),
Far = Origen{[Name="Far"]}[Data],
dbo_NOTARIOS = Far{[Schema="dbo",Item="NOTARIOS"]}[Data],
#"Consultas combinadas" = Table.NestedJoin(dbo_NOTARIOS, {"CODIGONOTARIO"}, PROTOCOLOS, {"CODIGOPROTOCOLO"}, "PROTOCOLOS", JoinKind.Inner)
in
#"Consultas combinadas"
Could somebody help me to replicate the substring function in Power BI, please?

SQL query case when then in where clause

I read a lot of similar questions but didn't find a solution for me. Basically I would like to have a where clause (AND PEKP.VORGANGS_ART = 'BE') only if a special condition (PFSP.EINKAUFS_KZ = 2) is true.
I tried in many ways like that:
SELECT *
FROM PFSP
LEFT OUTER JOIN PFAK on PFSP.RUECKMELDE_NR = PFAK.RUECKMELDE_NR
LEFT OUTER JOIN PEKP ON (PFSP.BESTELL_NR=PEKP.VORGANGS_NR)
AND (PFSP.BESTELL_POS_NR=PEKP.VORGANGS_POS_NR)
LEFT OUTER JOIN PMLB ON PFSP.KOMPONENTEN_ARTIKEL_NR=PMLB.ARTIKEL_NR
WHERE PFAK.KD_VORGANGS_NR = '910-001213'
AND PFSP.RUECKMELDE_STATUS = '3'
AND PFSP.BESCHAFFUNGSKENNER = 'F'
AND CASE PFSP.EINKAUFS_KZ
WHEN 2 THEN PEKP.VORGANGS_ART = 'BE'
END
but I keep getting errors:
wrong syntax near '='"
Skip the CASE, use AND/OR instead:
AND (PFSP.EINKAUFS_KZ <> 2 OR PEKP.VORGANGS_ART = 'BE')
If PFSP.EINKAUFS_KZ = 2, then PEKP.VORGANGS_ART must be equal to 'BE'.
If PFSP.EINKAUFS_KZ <> 2, it doesn't matter what PEKP.VORGANGS_ART is.
With this CASE expression:
AND 1 = CASE
WHEN PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART = 'BE' THEN 1
WHEN PFSP.EINKAUFS_KZ = 2 THEN 0
ELSE 1
END
The order of the conditions is important.
You probably want something like:
AND (
(PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART='BE')
OR PFSP.EINKAUFS_KZ <> 2 --You may need to catch NULL as well
)
SELECT *
FROM PFSP
LEFT OUTER JOIN PFAK on PFSP.RUECKMELDE_NR = PFAK.RUECKMELDE_NR
LEFT OUTER JOIN PEKP ON (PFSP.BESTELL_NR=PEKP.VORGANGS_NR)
AND (PFSP.BESTELL_POS_NR=PEKP.VORGANGS_POS_NR)
LEFT OUTER JOIN PMLB ON PFSP.KOMPONENTEN_ARTIKEL_NR=PMLB.ARTIKEL_NR
WHERE PFAK.KD_VORGANGS_NR = '910-001213'
AND PFSP.RUECKMELDE_STATUS = '3'
AND PFSP.BESCHAFFUNGSKENNER = 'F'
AND ((PFSP.EINKAUFS_KZ = 2 AND PEKP.VORGANGS_ART = 'BE') OR (PFSP.EINKAUFS_KZ <> 2) )

IF THEN in SQL Select Statement

I'm writing a report to return vendor names from journal transactions. Here are the basics of the query below.
I am using data from two views:
Journal detail view = pa_journal_detail
Vendor detail view = ap_vendor
Match on Vendor Number:
The vendor number is contained in the following fields:
ap_vendor.a_vendor_number
pa_journal_detail.jl_ref1 [under certain criteria shown below] ONLY WHEN the journal source code is "API" or "APM"
The source code is stored in the field pa_journal_detail. jl_source_code
The vendor name is stored in the field ap_vendor.a_vendor_name
This is the query I had started with. It is returning incorrect syntax errors when I attempt to run.
SELECT
CASE
WHEN pa_journal_detail. jl_source_code = ‘API’
OR pa_journal_detail. jl_source_code = ‘APM’
THEN(
SELECT a_vendor_name
FROM ap_vendor
INNER JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
ELSE 0
END as a_vendor_name, *
FROM pa_journal_detail
Here is the full query below. I have also tried it with the "TOP 1" included as well. I am now getting the error that there is incorrect syntax near the keyword AS.
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,(SELECT(CASE
WHEN pa_journal_detail. jl_source_code = 'API'
OR pa_journal_detail. jl_source_code = 'APM'
THEN(
SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number
)
ELSE 0
END as 'a_vendor_name', *
FROM pa_journal_detail))
FROM pa_journal_detail
This is what I ended up with and its working now! Thank you all!
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,iif((pa_journal_detail.jl_source_code = 'API'
OR pa_journal_detail.jl_source_code = 'APM')
,(SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
,0) as 'a_vendor_name'
FROM pa_journal_detail
for string compare you need to use single quote
CASE
WHEN pa_journal_detail. jl_source_code = 'API'
OR pa_journal_detail. jl_source_code = 'APM'
THEN(
SELECT top 1 a_vendor_name -- here you need limit or top 1
FROM ap_vendor
INNER JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number
)
ELSE 0
END as a_vendor_name, *
FROM pa_journal_detail
There is also iif(). I use it far more often than I should, I just like have a tiny little if for simple conditional work instead of big ole' Case statement.
select iif(1 = 1,'True','False')
-- any series that results in a boolean
select iif((1 = 1 and 0 = 0) and (5 / 1 = 5 and 5 % 10 = 5),'True','False')
for your query
SELECT
pa_journal_detail.a_project
,pa_journal_detail.jl_seg2
,pa_journal_detail.jl_seg3
,pa_journal_detail.jl_seg4
,pa_journal_detail.jl_source_code
,pa_journal_detail.jl_ref1
,pa_journal_detail.jl_gl_org
,pa_journal_detail.jl_gl_obj
,pa_journal_detail.jl_line_num
,pa_journal_detail.jl_journal_num
,pa_journal_detail.jl_jnl_year_period
,pa_journal_detail.jl_journal_number
,pa_journal_detail.jl_journal_seq
,iif(pa_journal_detail.jl_source_code = 'API' OR pa_journal_detail.jl_source_code = 'APM',(SELECT TOP 1 a_vendor_name
FROM ap_vendor
RIGHT JOIN pa_journal_detail
ON pa_journal_detail.jl_ref1 = ap_vendor.a_vendor_number)
,0)
'a_vendor_name', *
FROM pa_journal_detail))
FROM pa_journal_detail
I think a case expression may be the wrong tool for the job. If you want to join a table sometimes, a left join may be easier:
SELECT p.*, a.a_vendor_name
FROM pa_journal_detail p
LEFT JOIN ap_vendor a ON p.jl_ref1 = a.a_vendor_number AND
p.jl_source_code IN ('API', 'APM')

SQL query fails, no idea why

So I have just upgraded to MySQL 8 to test if it would be a viable option, but I have stumbled upon quiet the riddle.
It throws an error at 'table_product_features AS pf' but I can't seem to figure out why as in the documentation it is done exactly the same way: https://dev.mysql.com/doc/refman/8.0/en/join.html
Error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'groups ON pf.parent_id = groups.feature_id LEFT JOIN table_product_features_des' at line 1 (1064)
I also checked the bug tracker but that doesnt seem to have anything related to my issue.
What exactly am I doing wrong here?
P.S. I put it in a code snippet so that it would remain formatted.
SELECT pf.feature_id,
pf.company_id,
pf.feature_type,
pf.parent_id,
pf.display_on_product,
pf.display_on_catalog,
pf.display_on_header,
table_product_features_descriptions.description,
table_product_features_descriptions.lang_code,
table_product_features_descriptions.prefix,
table_product_features_descriptions.suffix,
pf.categories_path,
table_product_features_descriptions.full_description,
pf.status,
pf.comparison,
pf.position,
groups.position AS group_position,
table_product_features_values.value,
table_product_features_values.variant_id,
table_product_features_values.value_int
FROM table_product_features AS pf
LEFT JOIN table_product_features AS groups
ON pf.parent_id = groups.feature_id
LEFT JOIN table_product_features_descriptions
ON table_product_features_descriptions.feature_id = pf.feature_id
AND table_product_features_descriptions.lang_code = 'en'
INNER JOIN table_product_features_values
ON table_product_features_values.feature_id = pf.feature_id
AND table_product_features_values.product_id = 230
AND table_product_features_values.lang_code = 'en'
INNER JOIN table_ult_objects_sharing
ON ( table_ult_objects_sharing.share_object_id = pf.feature_id
AND table_ult_objects_sharing.share_company_id = 1
AND table_ult_objects_sharing.share_object_type =
'product_features' )
WHERE 1
AND pf.feature_type != 'G'
AND pf.status IN ( 'A' )
AND pf.display_on_product = 'Y'
AND ( pf.categories_path = ''
OR Isnull(pf.categories_path)
OR Find_in_set(203, pf.categories_path)
OR Find_in_set(215, pf.categories_path)
OR Find_in_set(216, pf.categories_path) )
GROUP BY pf.feature_id
ORDER BY group_position,
pf.position,
table_product_features_descriptions.description
If your not using aggregate functions I don't see why you need the GROUP BY.
Also groups is a reserved word, change it to tgroups or something else.
SELECT pf.feature_id,
pf.company_id,
pf.feature_type,
pf.parent_id,
pf.display_on_product,
pf.display_on_catalog,
pf.display_on_header,
tdesc.description,
tdesc.lang_code,
tdesc.prefix,
tdesc.suffix,
pf.categories_path,
tdesc.full_description,
pf.status,
pf.comparison,
pf.position,
tgroups.position group_position,
tvals.value,
tvals.variant_id,
tvals.value_int
FROM table_product_features pf
LEFT JOIN table_product_features tgroups ON pf.parent_id = tgroups.feature_id
LEFT JOIN table_product_features_descriptions tdesc ON tdesc.feature_id = pf.feature_id AND tdesc.lang_code = 'en'
INNER JOIN table_product_features_values tvals ON tvals.feature_id = pf.feature_id AND tvals.product_id = 230 AND tvals.lang_code = 'en'
INNER JOIN table_ult_objects_sharing tshar ON (tshar.share_object_id = pf.feature_id AND tshar.share_company_id = 1 AND tshar.share_object_type = 'product_features')
WHERE 1
AND pf.feature_type != 'G'
AND pf.status IN ('A')
AND pf.display_on_product = 'Y'
AND (pf.categories_path = '' OR Isnull(pf.categories_path) OR Find_in_set(203, pf.categories_path) OR Find_in_set(215, pf.categories_path) OR Find_in_set(216, pf.categories_path))
ORDER BY group_position, pf.position, tdesc.description

SQL avoid 0 in the calculation

Can anyone help me try to solve this equation? The "Lost_Weight" is a calculation field and I'm trying to get the result of HWeight - renWeight = '0' if the renWeight is 0. The where clause has a controversial statement that put a Challenge to me to make that happen. See below.
SELECT TOP (100) PERCENT dbo.Name.ID,
dbo.Name.CO_ID,
dbo.Name.FULL_NAME,
dbo.Name.STATE_PROVINCE, dbo.Tops_Profile.START_WGHT,
dbo.Tops_Profile.RENEWAL_WEIGHT,
dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT AS Lost_Weight,
dbo.Tops_Profile.H_WEIGHT,
dbo.Name.JOIN_DATE,
dbo.Name.BIRTH_DATE,
RIGHT(dbo.TOPS_AWARDS.AWARD_TYPE, 15) AS AWARDS_TYPE,
dbo.TOPS_AWARDS.AWARD_CATEGORY,
dbo.TOPS_AWARDS.AWARD_DATE,
dbo.vw_RegDirs.TARGET_ID AS
RD_ID,
dbo.vw_Coords.TARGET_ID AS Coord_ID,
dbo.vw_Coords.FULL_NAME AS
Coord_Name,
dbo.vw_AreaCapts.TARGET_ID AS AC_ID, dbo.Name.STATUS
FROM dbo.Name INNER JOIN dbo.Tops_Profile
ON dbo.Name.ID = dbo.Tops_Profile.ID
INNER JOIN dbo.vw_RegDirs
ON dbo.Name.CO_ID = dbo.vw_RegDirs.CHAPTER
INNER JOIN dbo.vw_Coords
ON dbo.Name.CO_ID = dbo.vw_Coords.CHAPTER
INNER JOIN dbo.vw_AreaCapts
ON dbo.Name.CO_ID = dbo.vw_AreaCapts.CHAPTER
LEFT OUTER JOIN dbo.TOPS_AWARDS
ON dbo.Name.ID = dbo.TOPS_AWARDS.ID
WHERE (dbo.Tops_Profile.RENEWAL_WEIGHT <> '0')
AND (dbo.Name.STATUS = 'a')
AND (dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT >= 100')
OR (dbo.Name.STATUS = 'a') AND (dbo.TOPS_AWARDS.AWARD_TYPE LIKE '%Century%')
right now if the renewal_weight is 0 it automatically give me the number from the H_WEIGHT in the Lost_Weight field and I need the result to be 0 if the RENEWAL_WEIGHT is 0.
I'm guessing 0 is a special value in this situation. This can be fixed by using CASE
Replace
dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT AS Lost_Weight
With
CASE WHEN RENEWAL_WEIGHT = 0 THEN 0
ELSE dbo.Tops_Profile.H_WEIGHT - dbo.Tops_Profile.RENEWAL_WEIGHT
END AS Lost_Weight