T-SQL force null value based on condition - sql

This is my view
SELECT e.Text AS StatusText,
a.Created AS [DATE],
a.Username,
b.Name AS CustomerName,
c.Name AS ServiceName,
d.Message AS DeviationMessage
FROM dbo.StatusUpdate AS a
LEFT OUTER JOIN dbo.Customer AS b ON a.CustomerId = b.CustomerID
LEFT OUTER JOIN dbo.Service AS c ON a.ServiceId = c.ServiceID
LEFT OUTER JOIN dbo.Deviation AS d ON a.DeviationId = d.DeviationID
LEFT OUTER JOIN dbo.StatusText AS e ON a.Status = e.ID
What i would like to do is: When a.Status(int) is 2 or 3, i would like to force a.Username to show as NULL. How should i approach this?

Try this:
SELECT e.Text AS StatusText,
a.Created AS [DATE],
CASE a.status
WHEN 2 THEN NULL
WHEN 3 THEN NULL
ELSE a.Username
END,
b.Name AS CustomerName,
c.Name AS ServiceName,
d.Message AS DeviationMessage
FROM dbo.StatusUpdate AS a
LEFT OUTER JOIN dbo.Customer AS b ON a.CustomerId = b.CustomerID
LEFT OUTER JOIN dbo.Service AS c ON a.ServiceId = c.ServiceID
LEFT OUTER JOIN dbo.Deviation AS d ON a.DeviationId = d.DeviationID
LEFT OUTER JOIN dbo.StatusText AS e ON a.Status = e.ID

You could achieve this pretty easily with a case statment.
So something like
CASE WHEN Status = 3 THEN USERNAME IS NULL
This is untested but the idea is there.

Related

remove and sum duplicate row in sql, can anyone give me insight for my query?

My query are like this
SELECT
A."name" AS so_name,
CASE
WHEN COUNT(*) OVER (PARTITION BY A."name") > 1
THEN CONCAT('duplicate')
ELSE CONCAT('is unique')
END AS tags,
e.total_qty AS sc_qty,
(SELECT DISTINCT (COALESCE(e.amount_total) * COALESCE (ai.base_currency_rate, 1))
FROM account_invoice ai
JOIN invoice_sale_rel isr ON isr.invoice_id = ai.ID
WHERE isr.sale_id = e.ID) AS sc_total
FROM
sale_quotation A
JOIN
res_partner b ON b.ID = A.partner_id
JOIN
sale_order e ON e.quotation_id = A.ID
LEFT JOIN
res_users C ON C.ID = A.user_id
LEFT JOIN
res_partner d ON d.ID = C.partner_id
WHERE
A.STATE != 'cancel'
AND e.STATE != 'cancel'
AND e.is_merchant = TRUE
ORDER BY
A.NAME ASC
And this is the result:
I am expecting the result would be like this, and add another values too
You need SUM() and GROUP BY
SELECT
A."name" AS so_name,
'is unique' AS tags,
SUM(e.total_qty) AS sc_qty /*,
(SELECT DISTINCT (COALESCE(e.amount_total) * COALESCE (ai.base_currency_rate, 1))*/
FROM account_invoice ai
JOIN invoice_sale_rel isr ON isr.invoice_id = ai.ID
WHERE isr.sale_id = e.ID) AS sc_total
FROM
sale_quotation A
JOIN
res_partner b ON b.ID = A.partner_id
JOIN
sale_order e ON e.quotation_id = A.ID
LEFT JOIN
res_users C ON C.ID = A.user_id
LEFT JOIN
res_partner d ON d.ID = C.partner_id
WHERE
A.STATE != 'cancel'
AND e.STATE != 'cancel'
AND e.is_merchant = TRUE
GROUP BY
A.NAME
ORDER BY
A.NAME ASC

My left join in oracle sql is not returning every element of the left table

i'm trying to get all the elements on the table B_ARTICULOS and make some calculations joining other tables (where some elements of B_ARTICULOS are not present) and I know I have to use a left join for that but I dont know what i'm doing wrong.
With this query I dont get every B_ARTICULOS, only those that are listed on the other tables
SELECT a.id, a.nombre,
CASE WHEN a.id IN dc.id_articulo THEN dc.cantidad ELSE 0 END CANTIDAD_COMPRAS,
CASE WHEN a.id IN dc.id_articulo THEN dc.cantidad * a.costo ELSE 0 END MONTO_COMPRAS,
CASE WHEN a.id IN dv.id_articulo THEN dv.cantidad ELSE 0 END CANTIDAD_VENTAS,
CASE WHEN a.id IN dv.id_articulo THEN dv.cantidad * a.precio ELSE 0 END MONTO_VENTAS
FROM B_ARTICULOS a
LEFT JOIN B_DETALLE_COMPRAS dc ON a.id = dc.id_articulo
JOIN B_COMPRAS c ON dc.id_compra = c.id
JOIN B_DETALLE_VENTAS dv ON dv.id_articulo = a.id
JOIN B_VENTAS v ON v.id = dv.id_venta
WHERE a.id IS NOT NULL;
The only explanation which I can see here is that you should be left joining to some of those other tables, beyond the second B_DETALLE_COMPRAS table. Assuming you would use left joins everywhere:
SELECT
a.id,
a.nombre,
CASE WHEN a.id IN dc.id_articulo THEN dc.cantidad ELSE 0 END CANTIDAD_COMPRAS,
CASE WHEN a.id IN dc.id_articulo THEN dc.cantidad * a.costo ELSE 0 END MONTO_COMPRAS,
CASE WHEN a.id IN dv.id_articulo THEN dv.cantidad ELSE 0 END CANTIDAD_VENTAS,
CASE WHEN a.id IN dv.id_articulo THEN dv.cantidad * a.precio ELSE 0 END MONTO_VENTAS
FROM B_ARTICULOS a
LEFT JOIN B_DETALLE_COMPRAS dc ON a.id = dc.id_articulo
LEFT JOIN B_COMPRAS c ON dc.id_compra = c.id
LEFT JOIN B_DETALLE_VENTAS dv ON dv.id_articulo = a.id
LEFT JOIN B_VENTAS v ON v.id = dv.id_venta
WHERE a.id IS NOT NULL;
You have to use left join too for other tables, like so:
...
FROM B_ARTICULOS a
LEFT JOIN B_DETALLE_COMPRAS dc ON a.id = dc.id_articulo
LEFT JOIN B_COMPRAS c ON dc.id_compra = c.id
LEFT JOIN B_DETALLE_VENTAS dv ON dv.id_articulo = a.id
LEFT JOIN B_VENTAS v ON v.id = dv.id_venta
...
Personally, I make subqueries for all the related tables that will be left joined to the main table. I grouped those tables then left join them to the main, like so:
...
FROM B_ARTICULOS a
LEFT JOIN (
SELECT dc.*
FROM B_DETALLE_COMPRAS dc
JOIN B_COMPRAS c ON dc.id_compra = c.id
) dc on a.id = dc.id_articulo
LEFT JOIN (
SELECT dv.*
FROM B_DETALLE_VENTAS dv
JOIN B_VENTAS v ON v.id = dv.id_venta
) dv ON dv.id_articulo = a.id
...

Tree Like Query On SQL Server

i have a query join 4 tables
SELECT
a.Id AS KelompokInformasi, d.Name AS Domain, d.Id AS Dimension, e.Text AS Description FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id like '%AAKX%'
the query result is
KelompokInformasi Domain Dimension Description
AAKX JWAAKT dim_JWAAKT Jangka Waktu Aset
AAKX KOKOLT dim_KOKOLT Kolektibilitas
AAKX SNOUPL dim_SNOUPL Status Operasional Usaha Pihak Lawan
AAKX is a parent from the other data in Domain, Dimension, and Description.
So, i want to change the query and in the end have an output query result like this:
KelompokInformasi Domain Dimension Description
AAKX NULL NULL NULL
NULL JWAAKT dim_JWAAKT Jangka Waktu Aset
NULL KOKOLT dim_KOKOLT Kolektibilitas
NULL SNOUPL dim_SNOUPL Status Operasional Usaha Pihak Lawan
I think you must use Group by with cube and having. Or grouping sets.
http://technet.microsoft.com/en-us/library/bb522495(v=SQL.105).aspx
SELECT
'KelompokInformasi' =
CASE
WHEN a.Id like '%AAKX%' THEN a.Id
ELSE NULL
END,
'Domain' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE d.Name
END,
'Dimension' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE d.Id
END,
'Description' =
CASE
WHEN a.Id like '%AAKX%' THEN NULL
ELSE e.Text
END,
FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id like '%AAKX%'
You can use Common table Expression(CTE),ROW_NUMBER() and Same Case statement used as above:
WITH cte AS
SELECT
a.Id AS KelompokInformasi,d.Name AS DOMAIN,d.Id AS Dimension,e.Text AS Description ,
ROW_NUMBER() OVER (PARTITION BY a.Id ORDER BY a.ID) AS COL5
FROM XBRLNamespaces a
INNER JOIN Hypercubes b
ON a.XBRLView_ViewId = b.XBRLView_ViewId
INNER JOIN HypercubeDimensionItems c
ON b.XBRLHypercubeId = c.XBRLHypercube_XBRLHypercubeId
INNER JOIN Items d
ON c.XBRLItem_ItemId = d.ItemId
INNER JOIN Labels e
ON d.ItemId = e.XBRLItem_ItemId
WHERE a.Id LIKE '%AAKX%' )
SELECT CASE
WHEN COL5 >1 THEN NULL ELSE KelompokInformasi END AS KelompokInformasi,
CASE
WHEN COL5=1 THEN NULL ELSE DOMAIN END AS DOMAIN,
CASE
WHEN COL5=1 THEN NULL ELSE Dimension END AS Dimension,
CASE
WHEN COL5=1 THEN NULL ELSE Description END AS Description
FROM cte

Left Join Yielding no results

I'm coming across an issue where when I write a query as so:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get several hundred results, but when I modify it to this:
SELECT a.v, b.w, c.x, d.y, e.z
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id AND c.n = 0
LEFT JOIN d
on b.code=d.code AND d.n = 0
JOIN e
on a.n = e.n
WHERE
a.zone = 10
WITH (nolock)
I get zero results.
From my understanding of SQL and left joins, I feel that getting any results with the first query means I should definitely get at least one result with the second, if only one where fields from c and d are null. Does PROGRESS implement outer joins in an unusual manner?
You might want to figure out what the c.n and d.n values are. Try something like this to figure out where your starting point is.
SELECT c.n, d.n, count(*)
FROM a
JOIN b
on a.id = b.id
LEFT JOIN c
on a.id = c.id
LEFT JOIN d
on b.code=d.code
JOIN e
on a.n = e.n
WHERE
a.zone = 10
group by c.n, d.n
Then you can adjust your query based on the result

Conditional INNER JOIN in SQL Server

I have a rather complex query that pretty much mimics a test query I have below:
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
INNER JOIN Group G ON C.CustomerId = G.CustomerId --Join only when C.code = 1
INNER JOIN GroupDetail D ON G.GroupId = D.DetailId --Join only when C.code = 1
WHERE G.Active = 1 AND --Only when C.code = 1
D.code = '1' AND --Only when C.code = 1
C.Id = #customerId
I'd like to do INNER JOINs on Group G and GroupDetail D (and ofcourse not have them in the WHERE conditions based on the table column C.code = 1
I replaced the INNER JOINs with LEFT OUTER JOINs for both the join conditions, but the result set is not what was expected
How do I conditionally do the JOIN
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
LEFT OUTER JOIN Group G ON C.CustomerId = G.CustomerId
LEFT OUTER JOIN GroupDetail D ON G.GroupId = D.DetailId
WHERE ((G.Active = 1 AND C.code = 1) OR G.Active IS NULL) AND
((D.code = '1' AND C.code = 1) OR D.code IS NULL) AND
C.Id = #customerId
I'm guessing you didn't include the IS NULL checks before so you never got to see rows where C.code <> 1 ?
You should check for NULL on a field that will never be null. This is almost always 'id', but it's not clear that you have a G.id or a D.id.
I'm guessing what you want is just a tighter ON clause, and a compound condition.
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD ON C.CustomerId = CD.CustomerId
INNER JOIN Address A ON CD.DetailID = A.DetailID
-- the next two joins happen only when c.code=1
-- their columns will be null when there is no match.
LEFT JOIN Group G ON C.CustomerId = G.CustomerId AND C.Code = 1
LEFT JOIN GroupDetail D ON G.GroupId = D.DetailId AND C.Code = 1
WHERE C.Id = #customerId AND --always check this
-- this condition is true if code is null or code isn't 1,
((C.code IS NULL or C.code <> 1)
-- or (if the code is 1), it is true if g.active and d.code
OR (G.Active = 1 AND D.code = '1'))
This will do a semi-join only when code is 1.
SELECT C.*
FROM Customer C
INNER JOIN CustDetail CD
ON C.CustomerId = CD.CustomerId
INNER JOIN Address A
ON CD.DetailID = A.DetailID
WHERE
C.Id = #customerId AND
(c.code != 1 OR
EXISTS(
SELECT NULL
FROM Group G
JOIN GroupDetail D ON G.GroupId = D.DetailId
WHERE
C.CustomerId = G.CustomerId AND
G.Active = 1 AND
D.code = '1'
))