Related
one table alphabet has column values nvarchar and values are (A,B,C,D,E,F,G,H)
we have another table that is linked with the previous one and this table has one column
which has values (C, H).
so These two values will be deleted from the previous table columns.
ID
values
1
A,B,C,D,E,F,G,H,I,J,K,L,M
2
A,C,F,G,H,J,U,V,W,X,Y,Z
second table.
ID
values
1
C,F
1
A,Z
FINAL OUTPUT .
TABLE A.
ID
values
1
B,D,E,G,H,I,J,K,L,M
2
A,C,F,G,H,J,U,V,W,X,Y,Z
Sample Query:
select
t1.id,
string_agg(t1.val1, ',') as "values"
from
(select "id", unnest(('{' || "values" || '}')::text[]) as val1 from table1
) as t1
left join
(select "id", unnest(('{' || "values" || '}')::text[]) val2 from table2
) t2 on t1.id = t2.id and t1.val1 = t2.val2
where t2.id is null
group by t1.id
-- Return:
id values
---------------------------------
1 B,D,E,G,H,I,J,K,L,M
2 A,C,F,G,H,X,J,U,V,W,Y,Z
I want the rows in which there is at least one column with a null value. I've tried to use a row expression like:
SELECT *
FROM <table>
WHERE <table> IS NULL
But it does not work. Is my query incorrect or?
PS I am using version 13.4
You can reference the table alias in the WHERE clause. The condition where the_table is not null would return the rows where all columns are not null.
The opposite of that (where at least one column is null) can be achieved by negating the expression:
select *
from the_table
where not (the_table is not null);
Looks a bit strange, but it's not the same as the_table is null - which is never true, as the reference to the table (alias) refers to an existing row. And if a row exists the the "whole row" can't be null.
This:
with the_table (col1, col2, col3) as (
values
(1,null,null),
(null,2,null),
(null,3,4),
(5,6,7)
)
select *
from the_table
where not (the_table is not null);
returns:
col1 | col2 | col3
-----+------+-----
1 | |
| 2 |
| 3 | 4
to check if the value is not null, you use the IS NOT NULL operator
value IS NOT NULL
The expression returns true if the value is NULL or false if it is not.
You need to mention your column name in the search.
SELECT * FROM <table_name> WHERE <column_name> IS NULL;
For more than one columns:
SELECT * FROM <table_name> WHERE <column1_name> IS NULL OR <column2_name> IS NULL;
There is some select
SELECT column1,
COUNT(CASE column2 WHEN 'type1' THEN 1 ELSE NULL END) AS Type1Count,
COUNT(CASE column2 WHEN 'type2' THEN 1 ELSE NULL END) AS Type2Count,
COUNT(CASE column2 WHEN 'type3' THEN 1 ELSE NULL END) AS Type3Count
FROM Yourtable
GROUP BY column1
help me please, how i can add column0 which values corresponds to column1 in select query, some thing like that
SELECT column0, column1,
COUNT(CASE column2 WHEN 'type1' THEN 1 ELSE NULL END) AS Type1Count,
COUNT(CASE column2 WHEN 'type2' THEN 1 ELSE NULL END) AS Type2Count,
COUNT(CASE column2 WHEN 'type3' THEN 1 ELSE NULL END) AS Type3Count
FROM Yourtable
GROUP BY column1
but my variant is not work...
When you are selecting the exact value of some columns, and aggregating (e.g. COUNT(), SUM()) on others, you need to tell the database which is which in the GROUP BY clause.
If you say:
GROUP BY column0, column1
Then for every unique combination of column0 and column1, you will get an extra row of results, with the COUNT() expressions calculated across all the rows in the table for that combination.
If you only want one row for each distinct value of column1, you need to instead tell the database which value of column0 you are interested in. For instance, you might ask for the minimum value of column0 for each column1 with this:
SELECT MIN(column0), column1 ... GROUP BY column1
Which means:
I want one row for each distinct value of ... (GROUP BY ...)
... column1 (... column1)
For each row, show me (SELECT):
The minimum value of column0 in that group
The value of column1 which will be the same for everything in that group
Lets say I have table with ID int, VALUE string:
ID | VALUE
1 abc
2 abc
3 def
4 abc
5 abc
6 abc
If I do select value, count(*) group by value I should get
VALUE | COUNT
abc 5
def 1
Now the tricky part, if there is count == 1 I need to get that ID from first table. Should I be using CTE? creating resultset where I will add ID string == null and run update b.ID = a.ID where count == 1 ?
Or is there another easier way?
EDIT:
I want to have result table like this:
ID VALUE count
null abc 5
3 def 1
If your ID values are unique, you can simply check to see if the max(id) = min(id). If so, then use either one, otherwise you can return null. Like this:
Select Case When Min(id) = Max(id) Then Min(id) Else Null End As Id,
Value, Count(*) As [Count]
From YourTable
Group By Value
Since you are already performing an aggregate, including the MIN and Max function is not likely to take any extra (noticeable) time. I encourage you to give this a try.
The way I would do it would indeed be a CTE:
using #group AS (SELECT value, Count(*) as count from MyTable GROUP BY value HAVING count = 1)
SELECT MyTable.ID, #group.value, #group.count from MyTable
JOIN #group ON #group.value = MyTable.value
When using group by, after the group by statement you can use a having clause.
So
SELECT [ID]
FROM table
GROUP BY [VALUE]
HAVING COUNT(*) = 1
Edit: with regards to your edited question: this uses some fun joins and unions
CREATE TABLE #table
(ID int IDENTITY,
VALUE varchar(3))
INSERT INTO #table (VALUE)
VALUES('abc'),('abc'),('def'),('abc'),('abc'),('abc')
SELECT * FROM (
SELECT Null as ID,VALUE, COUNT(*) as [Count]
FROM #table
GROUP BY VALUE
HAVING COUNT(*) > 1
UNION ALL
SELECT t.ID,t.VALUE,p.Count FROM
#table t
JOIN
(SELECT VALUE, COUNT(*) as [Count]
FROM #table
GROUP BY VALUE
HAVING COUNT(*) = 1) p
ON t.VALUE=p.VALUE
) a
DROP TABLE #table
maybe not the most efficient but something like this works:
SELECT MAX(Id) as ID,Value FROM Table WHERE COUNT(*) = 1 GROUP BY Value
-- Just a brief of business scenario is table has been created for a good receipt.
-- So here we have good expected line with PurchaseOrder(PO) in first few line.
-- And then we receive each expected line physically and that time these quantity may be different
-- due to business case like quantity may damage and short quantity like that.
-- So we maintain a status for that eg: OK, Damage, also we have to calculate short quantity
-- based on total of expected quantity of each item and total of received line.
if object_id('DEV..Temp','U') is not null
drop table Temp
CREATE TABLE Temp
(
ID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
Item VARCHAR(32),
PO VARCHAR(32) NULL,
ExpectedQty INT NULL,
ReceivedQty INT NULL,
[STATUS] VARCHAR(32) NULL,
BoxName VARCHAR(32) NULL
)
-- Please see first few line with PO data will be the expected lines,
-- and then rest line will be received line
INSERT INTO TEMP (Item,PO,ExpectedQty,ReceivedQty,[STATUS],BoxName)
SELECT 'ITEM01','PO-01','30',NULL,NULL,NULL UNION ALL
SELECT 'ITEM01','PO-02','20',NULL,NULL,NULL UNION ALL
SELECT 'ITEM02','PO-01','40',NULL,NULL,NULL UNION ALL
SELECT 'ITEM03','PO-01','50',NULL,NULL,NULL UNION ALL
SELECT 'ITEM03','PO-02','30',NULL,NULL,NULL UNION ALL
SELECT 'ITEM03','PO-03','20',NULL,NULL,NULL UNION ALL
SELECT 'ITEM04','PO-01','30',NULL,NULL,NULL UNION ALL
SELECT 'ITEM01',NULL,NULL,'20','OK','box01' UNION ALL
SELECT 'ITEM01',NULL,NULL,'25','OK','box02' UNION ALL
SELECT 'ITEM01',NULL,NULL,'5','DAMAGE','box03' UNION ALL
SELECT 'ITEM02',NULL,NULL,'38','OK','box04' UNION ALL
SELECT 'ITEM02',NULL,NULL,'2','DAMAGE','box05' UNION ALL
SELECT 'ITEM03',NULL,NULL,'30','OK','box06' UNION ALL
SELECT 'ITEM03',NULL,NULL,'30','OK','box07' UNION ALL
SELECT 'ITEM03',NULL,NULL,'10','DAMAGE','box09' UNION ALL
SELECT 'ITEM04',NULL,NULL,'25','OK','box10'
-- Below Table is my expected result based on above data.
-- I need to show those data following way.
-- So I appreciate if you can give me an appropriate query for it.
-- Note: first row is blank and it is actually my table header. :)
-- Conditions : any of row, we cant have ReceivedQty, DamageQty and ShortQty
-- values more than ExpectedQty value. Item03 has this scenario
-- Query should run in SQL 2000 DB
SELECT ''as'ITEM', ''as'PO#', ''as'ExpectedQty',''as'ReceivedQty',''as'DamageQty' ,''as'ShortQty' UNION ALL
SELECT 'ITEM01','PO-01','30','30','0' ,'0' UNION ALL
SELECT 'ITEM01','PO-02','20','15','5' ,'0' UNION ALL
SELECT 'ITEM02','PO-01','40','38','2' ,'0' UNION ALL
SELECT 'ITEM03','PO-01','50','50','0' ,'0' UNION ALL
SELECT 'ITEM03','PO-02','30','20','10' ,'10' UNION ALL
SELECT 'ITEM03','PO-03','20','0','0','20' UNION ALL
SELECT 'ITEM04','PO-01','30','25','0' ,'5'
Using this solution as a starting point, I've eventually ended up with this:
SELECT
Item,
PO,
ExpectedQty,
ReceivedQty = CASE
WHEN RemainderQty >= 0 THEN ExpectedQty
WHEN RemainderQty < -ExpectedQty THEN 0
ELSE RemainderQty + ExpectedQty
END,
DamageQty = CASE
WHEN RemainderQty >=0 OR ExpectedQty < -TotalRemainderQty THEN 0
WHEN RemainderQty < -ExpectedQty AND TotalRemainderQty > 0 THEN ExpectedQty
WHEN RemainderQty < -ExpectedQty AND TotalRemainderQty < -DamagedQty THEN ExpectedQty + TotalRemainderQty
WHEN RemainderQty > -DamagedQty THEN -RemainderQty
ELSE DamagedQty
END,
ShortQty = CASE
WHEN TotalRemainderQty >= 0 THEN 0
WHEN TotalRemainderQty < -ExpectedQty THEN ExpectedQty
ELSE -TotalRemainderQty
END
FROM (
SELECT
a.Item,
a.PO,
a.ExpectedQty,
b.DamagedQty,
RemainderQty = b.ReceivedQty - a.RunningTotalQty,
TotalRemainderQty = b.ReceivedQty + b.DamagedQty - a.RunningTotalQty
FROM (
SELECT
a.Item,
a.PO,
a.ExpectedQty,
RunningTotalQty = SUM(a2.ExpectedQty)
FROM (SELECT Item, PO, ExpectedQty FROM Temp WHERE STATUS IS NULL) AS a
INNER JOIN (SELECT Item, PO, ExpectedQty FROM Temp WHERE STATUS IS NULL) AS a2
ON a.Item = a2.Item AND a.PO >= a2.PO
GROUP BY
a.Item,
a.PO,
a.ExpectedQty
) a
LEFT JOIN (
SELECT
Item,
ReceivedQty = SUM(CASE STATUS WHEN 'OK' THEN ReceivedQty ELSE 0 END),
DamagedQty = SUM(CASE STATUS WHEN 'DAMAGE' THEN ReceivedQty ELSE 0 END)
FROM Temp
GROUP BY Item
) b ON a.Item = b.Item
) s;