How to get data from other table within a group by query? - sql-server

I have tried to group records from one table which have similar SerialNo. And I also want to show a column records from other table that has relation ship with table one using SerialNo.
I have a table 1:
And table 2:
My Query is:
select CIT_SERIALNUMBER, COUNT(CIT_ID)
as Cases from Table_2 where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1 order by min(CIT_CREATED) desc
Here is the result table:
In the query above I’ve got only CIT_SERIALNUMBER records from Table_2. But I also want to get the data from Table_1 column ComputerName. So, the expected result is:
Note: The two table 1 and 2 can be join by Column T1_Serial and CIT_SERIALNUMBER.
Please help me to re-write the sql query to achieve the expected result above.

If I understood your column names correctly, try this:
select CIT_SERIALNUMBER, ComputerName, COUNT(CIT_ID)
as Cases from Table_2 join Table_1 on Table_2.CIT_SERIALNUMBER=Table_1.Serial where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1 order by min(CIT_CREATED) desc

Try this-
SELECT A.ComputerName,
CIT_SERIALNUMBER,
COUNT(CIT_ID) AS Cases
FROM table_1 A
INNER JOIN Table_2 B ON A.Column T1_Serial = CIT_SERIALNUMBER.
WHERE B.CIT_SOURCEID LIKE '%E_One%'
AND (B.CIT_CREATED BETWEEN '2018-01-15' AND '2019-06-15')
AND B.CIT_SERIALNUMBER IS NOT NULL
GROUP BY A.ComputerName,B.CIT_SERIALNUMBER
HAVING COUNT(B.CIT_ID) > 1
ORDER BY MIN(B.CIT_CREATED) DESC;

It look odd, but I've got a solution for this:
I select all duplicated records from Table_2 first
Then I join Table_1 with result set of Table_2 to view column from both tables
Then I use another select to select data from result set above and group by all records.
Here is the query:
select z.CIT_SERIALNUMBER, z.ComputerName, z.Cases from (
SELECT y.CIT_SERIALNUMBER, x.ComputerName, y.Cases
FROM Table_1 x
right JOIN (
select CIT_SERIALNUMBER, COUNT(CIT_ID)
as Cases from Table_2 where CIT_SOURCEID like '%E_One%'
and (CIT_CREATED BETWEEN '2018-01-15'AND '2019-06-15') and CIT_SERIALNUMBER is not null
group by CIT_SERIALNUMBER
having COUNT(CIT_ID)>1
) y ON y.CIT_SERIALNUMBER = x.SerialNo) z group by CIT_SERIALNUMBER, z.ComputerName, z.Cases
Result set:

Related

T-SQL How to join to multiple tables depending on value

So I have some complicated production tables. What it comes down to, however, is that I'd like to be able to join to multiple tables depending on the where the value is that I'm seeking. Specifically, say I have an employee ID, "JHDOE", and I want to join it to the table where I can get that employee's name. The main table for employees is "Table A":
Notice that the field ID_2 does NOT have the value "JHDOE". Instead, it has "DOEJH". Well, there is another table that actually has the value I'm seeking, "Table B":
In this table, we do see "JHDOE" so at first I tried something like this:
from TableStart as start
left join TableB as b on
case
when start.EMP_ID like '[0-9]%'
then b.ID
else b.ID_2
end = start.EMP_ID
But this created other problems. So what I'd like to do is do something like join to EITHER table, or at least something to the same effect. One method I tried was this:
from TableStart as start
left join (select a.Name, a.ID, a.ID_2
from TableA as a
union
select b.Name, b.ID, b.ID_2
from TableB as b) names on
case
when start.EMP_ID like '[0-9]%'
then names.ID
else names.ID_2
end = start.EMP_ID
The result set for the union looks like this:
On my production data, this same scenario resulted in a blank. I suppose it doesn't know which row to join to? So I think I need to do something like pivot the rows into columns and then do an OR... but I'm not sure. I would be greatly appreciative of any guidance or instruction.
Instead of using a CASE in the join I think an IN operator would work. That will function as an OR (EMP_ID = ID or EMP_ID = ID_2). And if you LEFT JOIN from TableStart to both TableA and TableB and use the COALESCE function with each column from TableA and TableB you will get the first non-null value.
This assumes that if both TableA and TableB have a match for TableStart you are fine with taking the first non-null value which could result in a mixture of values from TableA and TableB if TableA has some null values.
select
start.*
, coalesce (a.Name, b.Name) as [Name]
, coalesce (a.ID, b.ID) as [ID]
, coalesce (a.ID_2, b.ID_2) as [ID_2]
from TableStart as start
left join TableA as a on start.EMP_ID in (a.ID, a.ID_2)
left join TableB as b on start.EMP_ID in (b.ID, b.ID_2)
Here is the full demo.

SQL Server : return value in specific table2 column based on value in table1

I have a query that gets data from 2 tables.
Transaction table contains week_id, customer_id, upc12, sales_dollars
Products table contains upc12, column_1, column_2, column_3
I want my query to return the value in products table, based on what the customer_id is in the transaction table. customer_id = 1 should return column_1, customer_id = 2 should return column_3, etc.
SELECT
t.week_id,
customer_id,
upc12,
p.___________ sum(t.sales_dollars)
FROM
transaction t, products p
WHERE
t.upc_12 = p.upc_12
GROUP BY
t.week_id, customer_id, upc12, p.___________
Sorry if this makes no sense, but my research hasn't been very good, as I don't know how to correctly formulate my question. You probably guessed I'm new to SQL.
Thanks!
Here is one way to do it:
;WITH cte as
(
SELECT
t.week_id,
customer_id,
upc12,
CASE customer_id
WHEN 1 THEN p.Column_1
WHEN 2 THEN p.Column_2
WHEN 3 THEN p.Column_3
END As ColByCustomer,
t.sales_dollars
FROM transaction t
INNER JOIN products p on t.upc_12 = p.upc_12
)
SELECT week_id, customer_id, upc12, ColByCustomer, SUM(sales_dollars)
FROM cte
GROUP BY week_id, customer_id, upc12, ColByCustomer

Updating table by using multiple joins on the same table

In the picture that is attached, I highlighted two columns. The left column is a the StartTime and the right column is an ID. I need the IDs that are NULL to be 164, since all 4 of those rows have the same exact StartTime. Is there a way to code one update statement to gather the NULL rows and rows with a value, and then update the NULL rows with a value that has the same StartTime? Any code would be very helpful.
Picture: Query Results
UPDATE t
SET t.ID = x.ID
FROM YourTable t
INNER JOIN (SELECT DISTINCT ID, StartTime
FROM YourTable
WHERE ID IS NOT NULL
) x
ON x.StartTime = t.StartTime
WHERE t.ID IS NULL
This is how I would do it.

Remove or adding additional string to a query

In Table 1, I have below data:
Stock_no Description
245685 Item1 Description
958565 Item2 Description
In Table 2, I have:
Barcode Item_no
48002456854582 000245685
48003658458693 000958565
In my query, I would like to JOIN the two tables, stock_no of table 1 is similar to the item_no of Table 2.
Is there a way where I could truncate 0's to the stock_no of Table1, or remove the leading 0's of Table2?
What I have so far:
SELECT A.stock_no, B.barcode, A.description
FROM A.Table1
JOIN B.Table2 ON A.stock_no = B.item_no
Because of the leading 000 of item_no in Table2, the above query would not work.
You can do, but this will not use index if any exists:
SELECT *
FROM Table1 t1
JOIN Table2 t2 ON CAST(t1.stock_no AS INT) = CAST(t2.item_no AS INT)
You can use subtring method like :
select substring(ColumnName, patindex('%[^0]%',ColumnName), 10)
Your select should look like this:
SELECT A.stock_no, B.barcode, A.description
FROM A.Table1 JOIN B.Table2
ON A.stock_no = substring(B.item_no,patindex('%[^0]%',B.item_no),10)
The second parameter '10' is max lenght of you item_no column

Need to return all columns from a table when using GROUP BY

I have a table let's say it has four columns
Id, Name, Cell_no, Cat_id.
I need to return all columns whose count of Cat_id is greater than 1.
The group should be done on Cell_no and Name.
What i have done so far..
select Cell_no, COUNT(Cat_id)
from TableName
group by Cell_Number
having COUNT(Cat_id) > 1
But what i need is some thing like this.
select *
from TableName
group by Cell_Number
having COUNT(Cat_id) > 1
Pratik's answer is good but rather than using the IN operator (which only works for single values) you will need to JOIN back to the result set like this
SELECT t.*
FROM tableName t
INNER JOIN
(SELECT Cell_no, Name
FROM TableName
GROUP BY Cell_no , Name
HAVING COUNT(Cat_id) > 1) filter
ON t.Cell_no = filter.Cell_no AND t.Name = filter.Name
you just need to modify your query like below --
select * from tableName where (Cell_no, Name) in (
select Cell_no, Name from TableName
Group by Cell_no , Name
having COUNT(Cat_id) > 1
)
as asked in question you want to group by Cell_no and Name.. if so you need to change your query for group by columns and select part also.. as I have mentioned
This version requires only one pass over the data:
SELECT *
FROM (SELECT a.*
,COUNT(cat_id) OVER (PARTITION BY cell_no)
AS count_cat_id_not_null
FROM TableName a)
WHERE count_cat_id_not_null > 1;

Resources