Like SQL Statement SQL Server 2008R2 - sql

I have a simple query but I have mutiple records I need to filter out. I'm using the like statment with wild cards. Is there a better way do do this then writing out each one? Can I create a udf, table that it refrences? How? If I can. Thanks :)
SELECT a.SalesOrderNo ,
a.ShipExpireDate ,
a.CustomerNo ,
b.ItemCode ,
b.LineKey ,
b.QuantityOrdered ,
b.QuantityShipped ,
b.ItemCodeDesc ,
b.ExplodedKitItem
FROM dbo.SO_SalesOrderHeader a
LEFT JOIN dbo.SO_SalesOrderDetail b
ON a.SalesOrderNo = b.SalesOrderNo
WHERE b.ItemType = '1'
AND b.ItemCodeDesc NOT LIKE '%Cert%'
AND b.ItemCodeDesc NOT LIKE '%Fee%'
AND b.ItemCodeDesc NOT LIKE '%Tag%'
AND b.ItemCode NOT LIKE 'GF%'
AND b.ItemCode NOT LIKE 'PXDIALPREP'
AND b.ItemCode NOT LIKE '/C%'
AND a.ShipExpireDate = CONVERT(DATE, GETDATE(), 101)

Here's a different design that lets you put ItemCodeDesc in a seperate table (this could also be a TVF). I can't comment on performance though.
On a different note, be aware that because you are outer joining to sales order detail, this table can have NULL records. In turn your b.ItemType = '1' will always be FALSE when ItemType is NULL. So you may as well make it an inner join (and you might find your query plan is doing that anyway)
SELECT a.SalesOrderNo ,
a.ShipExpireDate ,
a.CustomerNo ,
b.ItemCode ,
b.LineKey ,
b.QuantityOrdered ,
b.QuantityShipped ,
b.ItemCodeDesc ,
b.ExplodedKitItem
FROM dbo.SO_SalesOrderHeader a
LEFT JOIN dbo.SO_SalesOrderDetail b
ON a.SalesOrderNo = b.SalesOrderNo
WHERE b.ItemType = '1'
AND b.ItemCode NOT LIKE 'GF%'
AND b.ItemCode NOT LIKE 'PXDIALPREP'
AND b.ItemCode NOT LIKE '/C%'
AND a.ShipExpireDate = CONVERT(DATE, GETDATE(), 101)
AND NOT EXISTS (
SELECT 1 FROM dbo.MappingTable MT
WHERE b.ItemCodeDesc LIKE MT.ItemCodeDesc
)

Note: I am guessing that your criteria is meant to filter out item types that can't be shipped (like Fees), adjust as per your requirements.
The problem you are encountering is a result of discrete values being stored in an ID. Looks like you should have a column IsShippable, or better yet a code table for ItemCodeType with rows of Cert, Fee, Tag, etc. and the IsShippable column there. if you had a code table then you'd be able to do
inner join ItemCodeTypes ict on ict.ItemCodeTypeId = b.ItemCodeTypeId and ict.IsShippable = 1
Cert, Fee, Tag, rows in the ItemCodeTypes table would have IsShippable = 0:
Id | Name | IsShippable
1 Cert 0
2 Fee 0
3 Tag 0
4 Product 1
5 Book 1
Edit: To more directly answer your question, you could make a view like this, and then when you query from it easily filter on Where IsShippable = 1:
Select CASE
When b.ItemCodeDesc LIKE '%Cert%' Then 0
When b.ItemCodeDesc LIKE '%Fee%' Then 0
--etc.
Else 1
END as IsShippable
,*
From dbo.SO_SalesOrderDetail

Related

I want to show only the latest SQL Query

I have some issues with duplicate SQL tables. When I run the query, I am looking to show the MOST recent “Order ID.” When I run the program, it will show me every single order ID from the company. I only want to pull the latest order ID. Is there something wrong with my query? Is there something I can add or remove?
I want to see the latest order number, currently I see them all.
SELECT DISTINCT
payee.id AS 'Carrier ID'
, payee.status AS 'Status'
, CASE
WHEN payee.status = 'I' THEN 0
WHEN payee.status = 'A' THEN 100
ELSE 0
END AS 'Active %'
, drs_payee.icc_number AS 'MC #'
, payee.name AS 'Name'
, CAST(drs_payee.liab_expire_date AS DATE) AS 'Liab Date'
, CAST(drs.payee.cargo_ins_renew_dt AS DATE) AS 'Cargo Date'
, CONCAT(contact.email,'; ' ,drs_payee.ins_expire_notify) AS 'Emails'
, orders.id AS 'Order ID'
--, CAST(stop.sched_arrive_early AS DATE) AS 'Delivery Date'
FROM payee
LEFT JOIN drs_payee ON payee.id = drs_payee.id
INNER JOIN contact ON payee.id = contact.parent_row_id
LEFT JOIN movement ON payee.id = movement.override_payee_id
LEFT JOIN orders ON orders.curr_movement_id = movement.id
LEFT JOIN stop ON movement.dest_stop_id = stop.sched_arrive_early
WHERE contact.sequence = '1'
Try to use ORDER BY [column_name] desc along with query and LIMIT if required.

Oracle SQL How can I separate values from a column in two different columns?

I want to code a query to return description of some concepts and their respective price but I want to make two different columns to categorise two diferentes items categories of values. Is it possible?
SELECT b.descripcion CONCEPTO, a.cantidad, a.importe,
c.descripcion
FROM detalles_liquidaciones a
JOIN conceptos b
ON (a.codigo_concepto = b.codigo)
JOIN tipos_conceptos c
ON (b.codigo_tipo = c.codigo)
WHERE a.numero_liquidacion = 13802
AND c.descripcion IN ('HABER', 'RETENCION', 'ANTICIPO');
Output Query
I want to code something like this:
Ideal query
Could this work ? ( Perhaps there's a better solution, it feels a bit tricky... litterally "switching" ):
SELECT Concepto ,
(CASE
WHEN description LIKE 'HABER' THEN
importe
ELSE
NULL
END) haberes,
(CASE
WHEN description LIKE 'HABER' THEN
cantidad
ELSE
NULL
END) cantidad,
(CASE
WHEN description LIKE 'RETENCION' OR description LIKE 'ANTICIPO' THEN
importe
ELSE
NULL
END) retenciones
FROM (SELECT b.descripcion concepto, a.cantidad, a.importe, c.descripcion
FROM detalles_liquidaciones a
JOIN conceptos b
ON (a.codigo_concepto = b.codigo)
JOIN tipos_conceptos c
ON (b.codigo_tipo = c.codigo)
WHERE a.numero_liquidacion = 13802
AND c.descripcion IN ('HABER', 'RETENCION', 'ANTICIPO'));

Generating missing report submissions via reference table

I have a SQL query i'm currently working on which i would greatly appreciate some help with.
Here is a simplified version of the view I've been given to work on:
SELECT a.Organisation_Name
,a.Org_Id
,b.Activity_month
,SUM(b.Activity_Plan) 'Plan_Activity'
,SUM(b.Activity_Actual) 'Actual_Activity'
,SUM(b.Price_Actual) 'Actual_Price'
,SUM(b.Price_Plan) 'Plan_Price'
,COUNT(b.Instances) AS 'Record_Count'
,CASE WHEN COUNT(b.Instances) > 0 THEN 'Yes' ELSE 'No' END AS Submitted
FROM [ExampleDatabase].[dbo].[Organisation_Reference] a
LEFT JOIN [ExampleDatabase].[dbo].[Report_Submissions] b
ON a.Org_Id = b.Org_Id
AND ([Exmaple_Code] LIKE ('X') or [Example_Code] = 'X')
WHERE a.Category_Flag = 1
AND a.Example_Code in ('X','X','X','X','X')
GROUP BY
a.Organisation_Name
,a.Org_Id
,b.Activity_month
--
The Activity Month field is an Integer rather than a date, currently ranging from 1-8.
The problem i am facing is that within the [Report_Submissions] table, it only contains organisations which have actually submitted the reports, whereas the
[Organisation_Reference] table lists all the organisations which should be submitting.
Where the organisations have submitted the reports, the data is perfect and gives me a run down of all the details i need for each individual month.
Obviously if an organisation hasn't submitted then this detail wouldn't be available, but i do need to have a complete list of all organisations listed from the reference table for each individual month and whether they have submitted the reports or not.
At the moment where the 'Submitted' field = 'No' it's only bringing back one record for each organisation that has never submitted (With Activity_month coming through as null) and if an organisation has only submitted once or twice then it will include those submissions but still be missing the rest of the months from the result set.
I've tried various different joins etc. but I seem to be drawing a blank for a solution. Is there a way of generating this information within the script? Any advice would be great!
Kind Regards,
Mark
Since you just need numbers 1-8, using a subquery in your join to cross apply(values ()) to your Organisation_Reference table works well and does not make the query much more compliCated to read.
select
a.Organisation_Name
, a.Org_Id
, a.Activity_Month
, sum(b.Activity_Plan) 'Plan_Activity'
, sum(b.Activity_Actual) 'Actual_Activity'
, sum(b.Price_Actual) 'Actual_Price'
, sum(b.Price_Plan) 'Plan_Price'
, count(b.Instances) as 'record_count'
, case when count(b.Instances) > 0 then 'yes' else 'no' end as Submitted
from (
select o.*, t.Activity_Month
from [ExampleDatabase].[dbo].[Organisation_Reference] as o
cross apply (values (1),(2),(3),(4),(5),(6),(7),(8)) t(Activity_Month)
) as a
left join [ExampleDatabase].[dbo].[Report_Submissions] b
on a.Org_Id = b.Org_Id
and a.Activity_Month = b.Activity_Month
and ([exmaple_Code] like ('X') or [Example_Code] = 'X')
where a.Category_Flag = 1
and a.Example_Code in ('X','X','X','X','X')
group by
a.Organisation_Name
, a.Org_Id
, b.Activity_Month
You could also cross join with a numbers/tally table, or use a common table expression to generate the range of numbers you need. I would recommend either of those options as well, especially if your logic was more compliCated.
If Report_Submissions contains all of the months you want in your query, you could cross join the distinct Activity_Months from that table to your Organisation_Reference table.
select
a.Organisation_Name
, a.Org_Id
, a.Activity_Month
, sum(b.Activity_Plan) 'Plan_Activity'
, sum(b.Activity_Actual) 'Actual_Activity'
, sum(b.Price_Actual) 'Actual_Price'
, sum(b.Price_Plan) 'Plan_Price'
, count(b.Instances) as 'record_count'
, case when count(b.Instances) > 0 then 'yes' else 'no' end as Submitted
from (
select o.*, t.Activity_Month
from [ExampleDatabase].[dbo].[Organisation_Reference] as o
cross join (select distinct Activity_Month from Report_Submissions) t
) as a
left join [ExampleDatabase].[dbo].[Report_Submissions] b
on a.Org_Id = b.Org_Id
and a.Activity_Month = b.Activity_Month
and ([exmaple_Code] like ('X') or [Example_Code] = 'X')
where a.Category_Flag = 1
and a.Example_Code in ('X','X','X','X','X')
group by
a.Organisation_Name
, a.Org_Id
, b.Activity_Month

TSQL - Multiple Values in INSERT (because of joins)

Im trying to insert a data from one database to another. This is what i have so far, on the select side:
USE [db2]
SELECT
sP.pers_FirstName
,sp.pers_LastName
,sPH.Phon_Number
,CASE WHEN LEFT(sPH.Phon_Number, 2) = '04' THEN sPH.Phon_number ELSE NULL END
,CASE WHEN sp.pers_gender = 1 THEN 'M' WHEN sp.pers_gender = 2 THEN 'F' ELSE 'U' END
,CASE
WHEN sP.pers_salutation = '10' THEN 8
WHEN sp.pers_salutation = '6' THEN 2
WHEN sp.pers_salutation = '7' THEN 1
WHEN sp.pers_salutation = '8' THEN 4
WHEN sp.pers_salutation = '9' THEN 5
WHEN sp.pers_salutation = 'APROF' THEN 6
WHEN sp.pers_salutation = 'Ms.' THEN 4
WHEN sp.pers_salutation = 'PROF' THEN 6
END
,sp.pers_dob
,sp.pers_CreatedDate
,sp.pers_UpdatedDate
,'Candidate'
,1
,e.Emai_EmailAddress
,sP.pers_personID
FROM [db1].dbo.person sP
LEFT JOIN [db1].dbo.PhoneLink sPL ON sp.pers_personID = sPL.PLink_recordID
LEFT JOIN [db1].dbo.Phone sPH ON sPL.PLink_PhoneId = sPH.Phon_PhoneID
LEFT JOIN [db1].dbo.EmailLink eL ON sP.pers_personID = eL.ELink_RecordID
LEFT JOIN [db1].dbo.Email e ON eL.Elink_EmailID = e.Emai_EmailID
WHERE
(
sP.pers_employedby NOT IN (
'Aspen'
,'ACH'
)
)
OR
(
sP.pers_employedby IN (
'Aspen'
,'ACH'
)
AND sP.pers_personID NOT IN (
SELECT c.oppo_PrimaryPersonID FROM [SageCRM].dbo.Opportunity c
WHERE (c.oppo_contractcompleted <= '2016-01-01' OR c.oppo_contractterminated <= '2016-01-01') and c.Oppo_Deleted is null)
AND
sp.pers_isanemployee != 'ECHO'
AND sP.pers_personID IN (
SELECT c.oppo_PrimaryPersonID FROM [SageCRM].dbo.Opportunity c
WHERE c.oppo_Status != 'In Progress' OR c.oppo_Status = 'Completed')
AND sP.pers_dod IS NULL
AND sP.pers_FirstName NOT LIKE '%test%'
AND sP.pers_LastName NOT LIKE '%test%'
AND sp.pers_isanemployee != 'SalesContact'
)
Due to the fact that each person record can have multiple phone numbers linked to them, i end up with multiple records for each person, which obviously wont work as i will end up with duplicates when i actually insert the data.
The problem is, that i need to have all of the phone numbers for each record, just displayed in a different field (home phone, work phone, mobile phone).
Any Ideas, other than doing this in a separate insert statement for each phone / email link?
-------- EDIT: -----------------------------------------------------------------
Ok so, my bad for not giving you enough information. Both of your answers were good answers so thanks for that (#Horaciux, #John Wu).
However, there is no phoneType column, just a phone number. That being said, since every mobile starts with 04 and every home phone with anything else, i can pretty easily distinguish between the two phone types.
There are duplicates in the phone table though, so i will have to delete these, most likely via CTE, shouldn't be too hard.
So, i will end up with something like this for the two phone numbers:
SELECT (phon_number FROM phone p INNER JOIN PhoneLink p1 on p1.PhoneLinkID = p.PhoneLink WHERE LEFT(p.Phon_Number, 2) = '04')
SELECT (phon_number FROM phone p INNER JOIN PhoneLink p1 on p1.PhoneLinkID = p.PhoneLink WHERE LEFT(p.Phon_Number, 2) != '04')
My duplicate removal will be something like this:
WITH CTE AS
(
SELECT phon_linkID, phon_phonNumber, ROW_NUMBER() OVER (PARTITION BY phon_phonNumber ORDER BY phon_linkID) AS RN
FROM phone
)
DELETE FROM CTE WHERE RN<>1
Two easy steps.
Get rid of the joins to the phone number table.
Lookup the phone numbers per record by using a subquery in the select clause, one for each type of phone. Example
SELECT sP.pers_FirstName,
sP.pers_LastName,
(SELECT Phon_Number FROM Phone p JOIN PhoneLink pl ON pl.PhoneLinkID = p.PhoneLinkID WHERE pl.Person_ID = sP.pers_personID AND pl.Type = 'WORK') WorkPhone,
(SELECT Phon_Number FROM Phone p JOIN PhoneLink pl ON pl.PhoneLinkID = p.PhoneLinkID WHERE pl.Person_ID = sP.pers_personID AND pl.Type = 'HOME') HomePhone
FROM person
Without knowing your table's structure, I'll do some example.
select person.id,
max(case when phone.type='home' then phone.vlaue else 0 end) 'home',
max(case when phone.type='work' then phone.vlaue else 0 end) 'work'
from person,phone where...
group by person.id
Then use this query to join all other tables needed

Column 'dbo.User.FB_UserId' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause

I saw this error-message lots of times here, but I'm not getting the solution for my specific problem out of it (probably because I'm not an sql-expert), so please forgive me for posting a question to the same error.
This is the query I'm trying to execute:
SELECT DISTINCT U.FB_UserId
, U.Id AS GameUserID
, U.FbLocale
, U.FbGender
, U.FbBirthday
, U.RegistredAt
, U.LoginCount
, U.PlayCount
, U.MarketGroupId
, (SELECT COUNT(C.PriceFbCredits)
WHERE UserID = U.Id) AS Payments
, (SELECT SUM(CASE WHEN C.PriceFbCredits = 13 THEN 1 END)
WHERE UserID = U.Id) AS P13
, (SELECT SUM(CASE WHEN C.PriceFbCredits = 52 THEN 1 END)
WHERE UserID = U.Id) AS P52
, (SELECT SUM(CASE WHEN C.PriceFbCredits = 130 THEN 1 END)
WHERE UserID = U.Id) AS P130
FROM [dbo].[User] AS U WITH (NOLOCK) INNER JOIN [dbo].[FbCreditsCallback] AS C WITH (NOLOCK) ON C.UserId = U.Id
If I do, I get the error-message. OK, I know what it means and I kind of understand what to do, but I think if I do it doesn't give me the result I want...
I want some the data for a specific userid. some of the data needs to be summed, some of them need to be counted and in the result list each id should only appear once.
Now here's the funny thing (for me). If I write the inner SELECT-Queries like this, I'm not getting the error. But I don't know if the returned data is correct:
, (SELECT COUNT(PriceFbCredits)
FROM [dbo].[FbCreditsCallback]
WHERE UserID = U.Id) AS Payments
... To be honest, I kind of lost track and I'm hoping for some help.
below you'll see the correct SQL Server syntax when using grouping to make aggregation functions.
your WHERE UserID = U.Id is not needed at all since you are making it as part of the INNER JOIN clause.
So try this:
SELECT DISTINCT U.FB_UserId
, U.Id AS GameUserID
, U.FbLocale
, U.FbGender
, U.FbBirthday
, U.RegistredAt
, U.LoginCount
, U.PlayCount
, U.MarketGroupId
, COUNT(*) AS Payments
, SUM(CASE WHEN C.PriceFbCredits = 13 THEN 1 ELSE 0 END) AS P13
, SUM(CASE WHEN C.PriceFbCredits = 52 THEN 1 ELSE 0 END) AS P52
, SUM(CASE WHEN C.PriceFbCredits = 130 THEN 1 ELSE 0 END) AS P130
FROM [dbo].[User] AS U WITH (NOLOCK)
INNER JOIN [dbo].[FbCreditsCallback] AS C WITH (NOLOCK) ON C.UserId = U.Id
GROUP BY U.FB_UserId
, U.Id
, U.FbLocale
, U.FbGender
, U.FbBirthday
, U.RegistredAt
, U.LoginCount
, U.PlayCount
, U.MarketGroupId
as you wrote
i'm not an sql-expert
From now on, avoid using WITH(NOLOCK), is the same as if you asked SELECT [data] FROM [TABLE] WITH(I really, really don't care if it is accurate or not)
there are reasons to do that in some cases, but if you are a beginner with SQL I doubt that you are in such situation.
If you don't use GROUP BY then there will a conflict with the integrity on the select
ex
for a person it should have sum or count when u don't include that (person)
then for what do u expect a sum for