SQL Server order by query - sql-server

I have two tables called Listing and ListingProperties
Listing (ID, CurrentPrice)
ListingProperties (id, listingId, Fixedprice)
The problem is I want to order all listings by Fixedprice. But some listings don't have a Fixedprice.
In that case I want to check current price and compare with others Fixedprice and then order.
Listing
id name currentprice
1 a 10
2 b 50
3 c 40
ListingProperties
id listingId Fixedprice
1 1 20
2 3 30
after order the required order is
name
a
c
b

Try this:
SELECT Name
FROM Listing l
LEFT JOIN ListingProperties lp ON l.id=lp.listingid
ORDER BY ISNULL(lp.FixedPrice, l.currentprice)

Your question is not clear but I'll try to guess.
1) You have to join your tables:
SELECT <fields here>
FROM Listing L
LEFT JOIN ListingProperties LP
ON L.ID = LP.ListingId
This query assumes that you dont have REPEATED VALUES for a ListingId in ListingProperties. If you do have multiple values you have to specify priority criteria to decide which FixedPrice you want to show.
2) Once you have the joined query, you have to use the CASE statetemnt to select betwheen current and fixed. Tis assumes that you have AT LEAST ONE record in Listing for every item you want to list. If you do not have at least one, you'll have to do some forther tricks.
SELECT CASE WHEN L.CurrentPrice IS NULL THEN LP.FicedPrice ELSE L.CurrentPrice END
FROM Listing L
LEFT JOIN ListingProperties LP
ON L.ID = LP.ListingId
ORDER BY CASE WHEN L.CurrentPrice IS NULL THEN LP.FicedPrice ELSE L.CurrentPrice END

Related

How to Left Inner Join two queries in Sybase?

I have two queries that should be joined together. Here is my query 1:
SELECT
t1.rec_id,
t1.category,
t1.name,
t1.code,
CASE
WHEN t1.name= 'A' THEN SUM(t1.amount)
WHEN t1.name = 'D' THEN SUM(t1.amount)
WHEN t1.name = 'H' THEN SUM(t1.amount)
WHEN t1.name = 'J' THEN SUM(t1.amount)
END AS Amount
FROM Table1 t1
GROUP BY t1.name, t1.rec_id, t1.category, t1.code
Query 1 produce this set of results:
Rec ID Category Name Code Amount
1 1 A MIX 70927.00
1 3 D MIX 19922.00
1 2 H MIX 55104.00
1 4 J MIX 76938.00
Then I have query 2:
SELECT
CASE
WHEN t2.category_id = 1 THEN SUM(t2.sum)
WHEN t2.category_id = 2 THEN SUM(t2.sum)
WHEN t2.category_id = 3 THEN SUM(t2.sum)
WHEN t2.category_id = 4 THEN SUM(t2.sum)
END AS TotalSum
FROM Table2 t2
INNER JOIN Table1 t1
ON t1.amnt_id = t2.amnt_id
AND t2.unique_id = #unique_id
GROUP BY t2.category_id
The result set of query 2 is this:
TotalSum
186013.00
47875.00
12136.00
974602.00
All I need is this result set that combines query 1 and query 2:
Rec ID Category Name Code Amount TotalSum
1 1 A MIX 70927.00 186013.00
1 3 D MIX 19922.00 47875.00
1 2 H MIX 55104.00 12136.00
1 4 J MIX 76938.00 974602.00
As you can see there is connection between table 1 and table 2. That connection is amnt_id. However, I tried doing LEFT INNER JOIN on query 1 and then simply using same logic with case statement to get the total sum for table 2. Unfortunately Sybase version that I use does not support Left Inner Join. I'm wondering if there is other way to join these two queries? Thank you
I wondered if the CASE statement makes sense in the first query because it sums in every row. Are there other values for the name column except A, D, H, J? If not you can change the CASE statement to SUM(t1.amount) AS Amount. Also the GROUP BY in the first query seems dubious to me: you are grouping by the record id column - that means you are not grouping at all but instead return every row. If that is what you really want you can omit the SUM at all and just return the pure amount column.
As far as I understood your problem and your data structure: the values in Table2 are kind of category sums and the values in Table1 are subsets. You would like to see the category sum for every category in Table1 next to the single amounts?
You would typically use a CTE (common table expression, "WITH clause") but ASE doesn't support CTEs, so we have to work with joins. I recreated your tables in my SQL Anywhere database and put together this example. In a nutshell: both queries are subqueries in an outer query and are left joined on the category id:
SELECT *
FROM
(
SELECT
t1.rec_id,
t1.category,
t1.name,
t1.code,
CASE
WHEN t1.name= 'A' THEN SUM(t1.amount)
WHEN t1.name = 'D' THEN SUM(t1.amount)
WHEN t1.name = 'H' THEN SUM(t1.amount)
WHEN t1.name = 'J' THEN SUM(t1.amount)
END AS Amount
FROM Table1 t1
GROUP BY t1.rec_id, t1.name, t1.category, t1.code
) AS t1
LEFT JOIN
(
SELECT category_id, SUM(sum) FROM
table2
GROUP BY category_id
) AS totals(category_id, total_sum)
ON totals.category_id = t1.category;
This query gives me:
Rec ID Category Name Code Amount Category_id total_sum
2 3 D MIX 19922.00 3 47875.00
3 2 H MIX 55104.00 2 12136.00
1 1 A MIX 70927.00 1 186013.00
4 4 J MIX 76938.00 4 974602.00
You surely have to tweak it a bit including your t2.unique_id column (that I don't understand from your queries) but this is a practical way to work around ASE's missing CTE feature.
BTW: it's either an INNER JOIN (only the corresponding records from both tables) or a LEFT (OUTER) JOIN (all from the left, only the corresponding records from the right table) but a LEFT INNER JOIN makes no sense.

Understand below SQL Query

I need your help to understand below query can anyone help me to describe it, i wanted to know the role of b.id is null and r.id is null in below query if anyone can explain whole code then it would be great?
select l.id as start,
(
select min(a.id) as id
from sequence as a
left outer join sequence as b on a.id = b.id - 1
where b.id is null
and a.id >= l.id
) as end
from sequence as l
left outer join sequence as r on r.id = l.id - 1
where r.id is null;
This query returns your "islands"of your sequence, i.e. start and end of continuos id intervals.
You can read more on gaps and islands here: Special Islands and here The SQL of Gaps and Islands in Sequences
The query is finding islands of consecutive numbers, outputting the start and end of ranges where all consecutive numbers are there, so for the set if numbers
{1,3,4,5,6,9,10}
I would expect
1,1
2,6
9,10
to be selected
The outer query starts by finding number (N) that cannot join to a record holding N-1, detected by r.id is null
The sub query then finds the next highest number (M) that does not join to a record holding M+1 (detected using b.id is null)
so in my example 3 does not have a '2' to join to, meaning 3 begins a range. The first number >= to that with no subsequent record is 6, which has no '7' to make a join to
The query is joining two tables (in this case the same table but it does not matter) using an outer join.
if we have
SELECT t1.a, t1.b, t2.d
FROM table1 t1
LEFT OUTER JOIN table2 t2 ON t1.a = t2.a
WHERE t2.a is null
This means it returns a set of records with all those from table1, however its possible there will not be a joined record from table2 for every record in table1. If there isn't the table2 fields are returned as null so the the WHERE clause is effectively saying return me all records from table1 where we do not have a join record in table2.
In your example where it joins onto itself you are looking where there is not a next/previous record (depending upon which way you are looking at it) based upon the id e.g. if id = 5, then there is not a record with id = 4
Overall the sql as a whole looks like its returning the consecutive id ranges in the sequence table.

Conditional subquery that returns a running total

I am trying to run a subquery with a condition that returns a running total. However, I am receiving the following error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
Is there any way this code can be salvaged? Please be aware this code is part of a larger script that executes perfectly. The reason I need to keep it in this format is because it is the "missing piece", for lack of a better word.
SELECT A.[WeekEnding],
(
SELECT SUM(A.[Weekly Sales Units]), A.[Description], A.[WeekEnding]
FROM [FACT_SALES_HISTORY] A
INNER JOIN [DIM_DATE] B
ON A.WeekEnding = B.[WeekEnding] WHERE B.[YA Latest 1 Week] = 1
GROUP BY A.[Description], A.[WeekEnding]
) AS 'YA Units'
FROM [FACT_SALES_HISTORY] A
LEFT JOIN [DIM_DATE] B
ON A.WeekEnding = B.[WeekEnding]
The output data, from the code, would look like the following:
[Weekly Sales Units]) A.[Description] A.[WeekEnding]
24 Item One 03-10-2010
55 Item Two 03-10-2010
79 Item One 03-10-2010
98 Item Five 03-10-2010
11 Item Five 03-10-2010
You can't select three different items in your subquery and then use an AS assignment. You could split that into two separate queries and then union them.
SELECT SUM(A.[Weekly Sales Units]), A.[Description], A.[WeekEnding]
FROM [FACT_SALES_HISTORY] A
INNER JOIN [DIM_DATE] B
ON A.WeekEnding = B.[WeekEnding] WHERE B.[YA Latest 1 Week] = 1
GROUP BY A.[Description], A.[WeekEnding]
UNION ALL -- This will only union distinct columns
SELECT A.[WeekEnding]...<Your other columns>
FROM [FACT_SALES_HISTORY] A
t looks like your subquery on its own would provide the sample data and the outer query is trying to sum that up by weekending. If that is the case, then the whole thing could be replaced with this:
SELECT A.[WeekEnding], SUM(A.[Weekly Sales Units]) [YA Units]
FROM [FACT_SALES_HISTORY] A
INNER JOIN [DIM_DATE] B
ON A.WeekEnding = B.[WeekEnding] WHERE B.[YA Latest 1 Week] = 1
GROUP BY A.[WeekEnding]

How to display only the MAX results from a query

I am new to writing MS SQL queries and I am trying to display only the record with the highest field named RecordVersion.
Below is the query that works but displays all records:
SELECT
PriceCalendars.PriceProgramID,
PriceCalendars.EffectiveDateTime,
PriceSchedules.Price,
PriceSchedules.PLU,
items.Descr,
PriceSchedules.LastUpdate,
PriceSchedules.LastUpdatedBy,
PriceSchedules.RecordVersion,
PriceSchedules.PriceScheduleUniqueID
FROM
PriceCalendars
INNER JOIN PriceSchedules ON PriceCalendars.PriceProgramID = PriceSchedules.PriceProgramID
INNER JOIN items ON PriceSchedules.PLU = items.PLU
WHERE
(PriceSchedules.PLU = 'SLS10100103')
AND (PriceCalendars.EffectiveDateTime = '2016-03-22')
Here are the query results:
PriceProgramID EffectiveDateTime Price PLU Descr LastUpdate LastUpdatedBy RecordVersion PriceScheduleUniqueID
1 2016-03-22 00:00:00.000 35.00 SLS10100103 Architecture Adult from NP POS 2015-01-22 07:53:15.000 GX70,83 9 569
1 2016-03-22 00:00:00.000 32.00 SLS10100103 Architecture Adult from NP POS 2014-02-25 16:22:46.000 GX70,83 5 86180
The first line of the results has RecordVersion being 9 and the second line results is 5, I only want the higher record displaying, the one that returned RecordVersion = 9.
Every time I try to use the MAX command I get errors or the group by and I have tried every example I could find on the web but nothing seems to work.
Using MS SQL 2012.
Thanks,
Ken
Try the following query which attempts to solve your problem by ordering the returned rows by RecordVersion DESC and then SELECTs just the first row.
SELECT TOP 1
PriceCalendars.PriceProgramID,
PriceCalendars.EffectiveDateTime,
PriceSchedules.Price,
PriceSchedules.PLU,
items.Descr,
PriceSchedules.LastUpdate,
PriceSchedules.LastUpdatedBy,
PriceSchedules.RecordVersion,
PriceSchedules.PriceScheduleUniqueID
FROM
PriceCalendars
INNER JOIN PriceSchedules ON PriceCalendars.PriceProgramID = PriceSchedules.PriceProgramID
INNER JOIN items ON PriceSchedules.PLU = items.PLU
WHERE
(PriceSchedules.PLU = 'SLS10100103')
AND (PriceCalendars.EffectiveDateTime = '2016-03-22')
ORDER BY
RecordVersion DESC
All group by columns should be in select ,that's the rule of group by.How group by works is for every distinct combination of group by columns,arrange remaining columns into groups,so that any aggregation can be applied,in your case I am not sure what group by columns are unique with out test date.here is one version which use row number which gives you the output desired
Remember ,order by last updated date is the one which decides rows order and assign numbers
WITH CTE
AS
(
SELECT PriceCalendars.PriceProgramID,
PriceCalendars.EffectiveDateTime,
PriceSchedules.Price,
PriceSchedules.PLU,
items.Descr,
PriceSchedules.LastUpdate,
PriceSchedules.LastUpdatedBy,
PriceSchedules.RecordVersion,
PriceSchedules.PriceScheduleUniqueID,
ROW_NUMBER() OVER (PARTITION BY PriceSchedules.RecordVersion ORDER BY PriceSchedules.LastUpdatedBy) AS RN
FROM
PriceCalendars
INNER JOIN PriceSchedules ON PriceCalendars.PriceProgramID = PriceSchedules.PriceProgramID
INNER JOIN items ON PriceSchedules.PLU = items.PLU
WHERE
(PriceSchedules.PLU = 'SLS10100103')
AND (PriceCalendars.EffectiveDateTime = '2016-03-22')
)
SELECT * FROM CTE WHERE RN=1

Counting duplicate items in different order

Goal:
To know if we have purchased duplicate StockCodes or Stock Description more than once on difference purchase orders
So, if we purchase Part ABC on Purchase Order 1 and Purchase Order 2, it should return the result of
PurchaseOrders, Part#, Qty
Purchase Order1, Purchase Order2, ABC, 2
I just don't know how to pull the whole code together, more to the point, how do I know if it's occurred on more than 1 Purchase Order without scrolling through all the results , may also have to do with Multiple (Having Count) Statements as I only seem to be doing by StockCode
SELECT t1.PurchaseOrder,
t1.MStockCode,
Count(t1.MStockCode) AS SCCount,
t1.MStockDes,
Count(t1.MStockDes) AS DescCount
FROM PorMasterDetail t1
INNER JOIN PorMasterHdr t2
ON t1.PurchaseOrder = t2.PurchaseOrder
WHERE Year(t2.OrderEntryDate) = Year(Getdate())
AND Month(t2.OrderEntryDate) = Month(Getdate())
GROUP BY t1.PurchaseOrder,
t1.MStockCode,
t1.MStockDes
HAVING Count(t1.MStockCode) > 1
Using responses I came up with the following
select * from
(
SELECT COUNT(dbo.InvMaster.StockCode) AS Count, dbo.InvMaster.StockCode AS StockCodes,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
FROM dbo.InvMaster INNER JOIN dbo.PorMasterDetail ON
dbo.InvMaster.StockCode = dbo.PorMasterDetail.MStockCode
INNER JOIN dbo.PorMasterHdr ON dbo.PorMasterDetail.PurchaseOrder = dbo.PorMasterHdr.PurchaseOrder
WHERE YEAR(dbo.PorMasterHdr.OrderEntryDate) = YEAR(GETDATE())
GROUP BY dbo.InvMaster.StockCode, dbo.InvMaster.StockCode,
dbo.PorMasterDetail.PurchaseOrder, dbo.PorMasterHdr.OrderEntryDate
) Count
Where Count.Count > 1
This returns the below , which is starting to be a bit more helpful
In result line 2,3,4 we can see the same stock code (*30044) ordered 3 times on different
purchase orders.
I guess the question is, is it possible to look at If something was ordered more than once within say a 30 day period.
Is this possible?
Count StockCodes PurchaseOrder OrderEntryDate
2 *12.0301.0021 322959 2014-09-08
2 *30044 320559 2014-01-21
8 *30044 321216 2014-03-26
4 *30044 321648 2014-05-08
5 *32317 321216 2014-03-26
4 *4F-130049/TEST 323353 2014-10-22
5 *650-1157/E 322112 2014-06-24
2 *650-1757 321226 2014-03-27
SELECT *
FROM
(
SELECT h.OrderEntryDate, d.*,
COUNT(*) OVER (PARTITION BY d.MStockCode) DupeCount
FROM
PorMasterHdr h
INNER JOIN PorMasterDetail d ON
d.PurchaseOrder = h.PurchaseOrder
WHERE
-- first day of current month
-- http://blog.sqlauthority.com/2007/05/13/sql-server-query-to-find-first-and-last-day-of-current-month/
h.OrderEntryDate >= CONVERT(VARCHAR(25), DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()),101)
) dupes
WHERE
dupes.DupeCount > 1;
This should work if you're only deduping on stock code. I was a little unclear if you wanted to dedupe on both stock code and stock desc, or either stock code or stock desc.
Also I was unclear on your return columns because it almost looks like you're wanting to pivot the columns so that both purchase order numbers appear on the same line.

Resources