T-SQL Merging data - sql-server

I've imported data from an XML file by using SSIS to SQL Server.
The result what I got in the database is similar to this:
+-------+---------+---------+-------+
| ID | Name | Brand | Price |
+-------+---------+---------+-------+
| 2 | NULL | NULL | 100 |
| NULL | SLX | NULL | NULL |
| NULL | NULL | Blah | NULL |
| NULL | NULL | NULL | 100 |
+-------+---------+---------+-------+
My desired result would be:
+-------+---------+---------+-------+
| ID | Name | Brand | Price |
+-------+---------+---------+-------+
| 2 | SLX | Blah | 100 |
+-------+---------+---------+-------+
Is there a pretty solution to solve this in T-SQL?
I've already tried it with a SELECT MAX(ID) and then a GROUP BY ID, but I'm still stuck with the NULL values. Also I've tried it with MERGE, but also a failure.
Could someone give me a direction where to search further?

You can select MAX on all columns....
SELECT MAX(ID), MAX(NAME), MAX(BRAND), MAX(PRICE)
FROM [TABLE]
Click here for a fiddley fidd fiddle...

Related

T-SQL Query comparing Member counts between 2 tables

TABLE 1: Data sent to vendor
| MemberID | FirstName | LastName | Etc |
| :------: | :-------: | :------: | :-: |
| 1 | John | Smith | Etc |
| 2 | Jane | Doe | Etc |
| 3 | Dan | Laren | Etc |
TABLE 2: Data returned from vendor
| MemberID | FirstName | LastName | Etc |
| :------: | :-------: | :------: | :-: |
| 1 | John | Smith | Etc |
| 2 | Jane | Doe | Etc |
| 3 | Dan | Laren | Etc |
We send data to a vendor which is used for their matching algorithm and they return the data with new information. The members are matched with a MemberID data element. How would I write a query which shows me which MemberIDs we sent to the vendor but the vendor didn't return?
NOT EXITS would be my first choice here.
Example
SELECT *
FROM Table1 A
WHERE NOT EXISTS (SELECT 1
FROM Table2 B
WHERE A.MemberID = B.MemberID )
SELECT MemberID
FROM Table1
WHERE MemberID NOT IN (SELECT MemberID FROM Table2)
Using EXCEPT is one option.
SELECT sent.[MemberID] FROM Tbl1_SentToVendor sent
EXCEPT
SELECT recv.[MemberID] FROM Tbl2_ReturnedFromVendor recv
This is just on MemberID, but the "EXCEPT" syntax can also support additional columns (e.g., in case you want to filter out data that may be the same as what you already have.)

SQL Server : update sequence number across multiple groups

I would like to update a table:
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | NULL |
| 2 | 1 | 2010-04-27 | NULL |
| 3 | 2 | 2010-04-28 | NULL |
| 4 | 3 | 2010-04-28 | NULL |
To this (note that created_at is used for ordering, and sequence is "grouped" by type_id):
| id | type_id | created_at | sequence |
|----|---------|------------|----------|
| 1 | 1 | 2010-04-26 | 1 |
| 2 | 1 | 2010-04-27 | 2 |
| 3 | 2 | 2010-04-28 | 1 |
| 4 | 3 | 2010-04-28 | 1 |
Same question has been raised but for SQL Server.
Link
Thanks.
You can use ROW_NUMBER() to get sequence number per type_id slice. Use a CTE to make UPDATE operation simpler:
;WITH ToUpdate AS (
SELECT id, type_id, created_at, sequence,
ROW_NUMBER() OVER (PARTITION BY type_id ORDER BY created_at) AS newSeq
FROM mytable
)
UPDATE ToUpdate
SET sequence = newSeq
Demo here

Group by Date bigger than SQL Server

I'm working with Micrososft SqlServer 2012 and I have this table:
Table
+-----------+--------+------------+
| Id_Client | Amount | Date |
+-----------+--------+------------+
| 1 | 100 | 24/08/2015 |
| 2 | 100 | 24/07/2015 |
| 3 | 100 | 24/06/2015 |
| 3 | 100 | 24/05/2015 |
+-----------+--------+------------+
And I need to make a query like this:
Query
SELECT ID_CLIENT,
CASE WHEN DATE <= '01/07/2015' THEN 'OLD' ELSE 'NEW' END,
SUM(AMOUNT) FROM TABLE
GROUP BY ID_CLIENT
How do I Group by Date with the condition, instead of each Date?
I expect something like:
Expected result
+---+-----+-----+
| 1 | NEW | 100 |
| 2 | NEW | 100 |
| 3 | OLD | 200 |
+---+-----+-----+

Query a query's column name in SQL Server

I want to query in SQL Server a column's name. I know it is possible to get a table's columns from the system table, but unfortunately that's not enough for me.
Example:
I have a table that contains an ID column and a string column. The table's name is test, and it has a testID and a test column.
This query:
select column_name
from information_schema.columns
where table_name = 'teszt'
return the names of the columns of my table. So it returns testID and Test.
What I want is when I use a query like this:
select count(*) as Amount from test
I want a query that can return the column names of my query. So in this specific case it returns the string 'Amount'. I don't know if that is possible.
Not sure if there is an easier way of getting the name of columns with aliases, but one way of doing it is via XML. This query will return one row per column in the inner query:
select T1.res.value('local-name(.)', 'varchar(50)')
from (select cast(
(
select count(*) as Amount from test
for xml raw) as xml
)) q(res)
CROSS APPLY q.res.nodes('/row/#*') as T1(res)
In SQL Server 2012 you have a stored procedure that you can use for exactly this purpose.
sp_describe_first_result_set (Transact-SQL)
SQL Fiddle
MS SQL Server 2012 Schema Setup:
create table test(id int);
Query 1:
exec sp_describe_first_result_set N'select count(*) as Amount from test'
Results:
| IS_HIDDEN | COLUMN_ORDINAL | NAME | IS_NULLABLE | SYSTEM_TYPE_ID | SYSTEM_TYPE_NAME | MAX_LENGTH | PRECISION | SCALE | COLLATION_NAME | USER_TYPE_ID | USER_TYPE_DATABASE | USER_TYPE_SCHEMA | USER_TYPE_NAME | ASSEMBLY_QUALIFIED_TYPE_NAME | XML_COLLECTION_ID | XML_COLLECTION_DATABASE | XML_COLLECTION_SCHEMA | XML_COLLECTION_NAME | IS_XML_DOCUMENT | IS_CASE_SENSITIVE | IS_FIXED_LENGTH_CLR_TYPE | SOURCE_SERVER | SOURCE_DATABASE | SOURCE_SCHEMA | SOURCE_TABLE | SOURCE_COLUMN | IS_IDENTITY_COLUMN | IS_PART_OF_UNIQUE_KEY | IS_UPDATEABLE | IS_COMPUTED_COLUMN | IS_SPARSE_COLUMN_SET | ORDINAL_IN_ORDER_BY_LIST | ORDER_BY_IS_DESCENDING | ORDER_BY_LIST_LENGTH | TDS_TYPE_ID | TDS_LENGTH | TDS_COLLATION_ID | TDS_COLLATION_SORT_ID |
|-----------|----------------|--------|-------------|----------------|------------------|------------|-----------|-------|----------------|--------------|--------------------|------------------|----------------|------------------------------|-------------------|-------------------------|-----------------------|---------------------|-----------------|-------------------|--------------------------|---------------|-----------------|---------------|--------------|---------------|--------------------|-----------------------|---------------|--------------------|----------------------|--------------------------|------------------------|----------------------|-------------|------------|------------------|-----------------------|
| 0 | 1 | Amount | 1 | 56 | int | 4 | 10 | 0 | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 0 | 0 | 0 | (null) | (null) | (null) | (null) | (null) | 0 | (null) | 0 | 0 | 0 | (null) | (null) | (null) | 38 | 4 | (null) | (null) |
Maybe you want something like this? :-)
SELECT AMOUNT
FROM
(
SELECT COUNT(*) AS AMOUNT
FROM TEST
)X

Rearranging and deduplicating SQL columns based on column data

Sorry I know that's a rubbish Title but I couldn't think of a more concise way of describing the issue.
I have a (MSSQL 2008) table that contains telephone numbers:
| CustomerID | Tel1 | Tel2 | Tel3 | Tel4 | Tel5 | Tel6 |
| Cust001 | 01222222 | 012333333 | 07111111 | 07222222 | 01222222 | NULL |
| Cust002 | 07444444 | 015333333 | 07555555 | 07555555 | NULL | NULL |
| Cust003 | 01333333 | 017777777 | 07888888 | 07011111 | 016666666 | 013333 |
I'd like to:
Remove any duplicate phone numbers
Rearrange the telephone numbers so that anything beginning with "07" is the first phone number. If there are multiple 07's, they should be in the first fields. The order of the numbers apart from that doesn't really matter.
So, for example, after processing, the table would look like:
| CustomerID | Tel1 | Tel2 | Tel3 | Tel4 | Tel5 | Tel6 |
| Cust001 | 07111111 | 07222222 | 01222222 | 012333333 | NULL | NULL |
| Cust002 | 07444444 | 07555555 | 015333333 | NULL | NULL | NULL |
| Cust003 | 07888888 | 07011111 | 016666666 | 013333 | 01333333 | 017777777 |
I'm struggling to figure out how to efficiently achieve my goal (there are 600,000+ records in the table). Can anyone help?
I've created a fiddle if it'll help anyone play around with the scenario.
You can break up the numbers into individual rows using UNPIVOT, then reorder them based on the occurence of the '07' prefix using ROW_NUMBER(), and finally recombine it using PIVOT to end up with the 6 Tel columns again.
select *
FROM
(
select CustomerID, Col, Tel
FROM
(
select *, Col='Tel' + RIGHT(
row_number() over (partition by CustomerID
order by case
when Tel like '07%' then 1
else 2
end),10)
from phonenumbers
UNPIVOT (Tel for Seq in (Tel1,Tel2,Tel3,Tel4,Tel5,Tel6)) seqs
) U
) P
PIVOT (MAX(TEL) for Col IN (Tel1,Tel2,Tel3,Tel4,Tel5,Tel6)) V;
SQL Fiddle
Perhaps using cursor to collect all customer id and sorting the fields...traditional sorting technique as we used to do in school c++ ..lolz...like to know if any other method possible.
If you dont get any then it is the last way . It will take a long time for sure to execute.

Resources