I have two tables.
One is inventorytable with columns PO No,index,item name,amount,date,
PO Index Item amount date unit price
PO01 1 pen 20 1/2/2018 10
PO01 2 pad 15 1/3/2018 10
PO02 1 book 30 2/5/2018 10
Another table is paymentrecord with PO No,index,item name, amount, value.
PO Index Item amount
PO01 1 pen 10
PO01 2 pad 15
How to find inventory not paid or not fully paid?
PO Index Item amount unpaid value
PO01 1 pen 10 100
PO02 1 book 30 3000
I tried following sql
select *
from inventory
where not exists (select inventory.PONo,inventory.index
from inventory,payment
where inventory.PO=payment.PO )
but it returns nothing
Use an outer join to link payments to inventory. Filter on payment.amount being less than the calculated value of the inventory items, unit_price * amount:
select i.po_no
, i.Index
, i.Item
, i.amount
, ((i.unit_price * i.amount) - nvl(p.amount, 0) as unpaid_value
from inventory i
left join payment p
on p.po_no = i.po_no
and p.index = i.index
where (i.unit_price * i.amount) > nvl(p.amount, 0)
/
Note: the names of things are inconsistent across all your examples. So you may need to tweak this solution to make it run on your schema.
I guess you will need both, PO and Index, to uniquely identify record.
Try out below.
select * from inventory
where not exists
(select 1 from inventory,payment where inventory.PO=payment.PO and inventory.Index=payment.Index)
You can use below query
select i.ipo, i.iindex, i.iitem,
(i.iamount - coalesce(p.pamount,0)) as Tamount
from payment p right outer join invent i
on (i.ipo = p.ppo and i.iindex = p.pindex and i.iitem = p.pitem)
where i.iamount != coalesce(p.pamount,0)
This is result in
ipo iindex iitem Tamount
PO01 1 pen 10
PO02 1 book 30
Table structure followed is
create table invent
(
iPO varchar(4),
iIndex int,
iItem varchar(10),
iamount int,
idate date,
iunit_price int);
create table payment
(
pPO varchar(4),
pIndex int,
pItem varchar(10),
pamount int);
Hope following query helps. Use same column name instead of *.
select * from inventory
Except
select * from payment
Related
I´ve been trying to automize a list of addresses in SQL. I have multiple addresses and quantities and i need only the addresses that will fulfill the quantity i need
For example:
I have a table with
Item A qty 20
Item B qty 5
Item C qty 23
And a table with addresses and units
Address 1 item A 15units
Address 2 item A 10units
Address 3 item A 10units
Address 4 item A 13units
The result should show only
Address 2 item A 10units
Address 3 item A 10units
Assuming that your first table sales stores the sales made :
Item
qty
A
20
B
5
C
23
and your second table stocks indicates the addresses of the stored items :
Address
item
units
1
A
15
2
A
10
3
A
10
4
A
13
then you can select a subset of addresses so that the sum of the stored units is equal or greater than the quantity sold :
WITH list AS (
SELECT st.item
, sa.qty AS sales_qty
, array_agg(st.address) OVER w AS addresses
, array_agg(st.units) OVER w AS units
, sum(units) OVER w AS total_stored_units
FROM sales AS sa
INNER JOIN stocks AS st
ON st.item = sa.item
WINDOW w AS (PARTITION BY st.item ORDER BY st.address)
)
SELECT DISTINCT ON (item)
item, unnest(addresses) AS address, unnest(units) AS units
FROM list
WHERE total_stored_units >= sales_qty
ORDER BY item, total_stored_units ASC
Result
item
address
units
A
1
15
A
2
10
see dbfiddle
Thanks a lot #Edouard!
I ended up using something like
WITH r AS
(
SELECT
item,
address,
quantity,
sum(quantity)
OVER (
PARTITION BY item
ORDER BY quantity desc
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) as total_units
FROM st
GROUP BY 1,2,3
)
SELECT *
FROM r
GROUP BY 1,2,3,4
HAVING total_units <= qty_needed + avg(units)
ORDER BY units desc
I couldnt run your query in the bigquery console, but from it a re read some documentation of windows functions find this solution.
Again, thanks a lot!
I have two tables to main orders and ordered products.
Table 1: ORDERS
"CREATE TABLE IF NOT EXISTS ORDERS("
"id_order INTEGER PRIMARY KEY AUTOINCREMENT,
"o_date TEXT,"
"o_seller TEXT,"
"o_buyer TEXT,"
"o_shipping INTEGER,"
"d_amount INTEGER,"
"d_comm INTEGER,"
"d_netAmount INTEGER)"
Table 2: ORDERED_PRODUCTS
"CREATE TABLE IF NOT EXISTS dispatch_products("
"id_order INTEGER NOT NULL REFERENCES ORDERS(id_order),"
"product_name INTEGER,"
"quantity INTEGER,"
"rate INTEGER)"
I tried to join these two tables using following query:
SELECT *
FROM ORDERS a
INNER JOIN ORDERED_PRODUCTS b
ON a.id_order = b.id_order
WHERE a.buyer = 'abc'
The issue is with the entries with multiple products in table 2.
The output I'm getting is like below:
order_ID date seller buyer Ship amt comm nAmt Prod Qty Rate
1 A x 5 100 5 115 Scale 10 10
2 B abc 10 100 5 115 pen 5 10
2 B abc 10 100 5 115 paper 10 5
3 C xyz 10 100 5 220 book 5 20
3 C xyz 10 100 5 220 stapl 10 10
expected output:
order_ID date seller buyer Ship amt comm nAmt Prod Qty Rate
1 A x 5 100 5 115 Scale 10 10
2 B abc 10 100 5 115 pen 5 10
Paper 10 5
3 C xyz 10 100 5 220 Book 5 20
Stapl 10 10
Databases don't really work like that; you got what you asked for, and with no duplicates (all rows are different). You're looking at the columns of data that came from orders and saying "oh, the data is duplicated" but it isn't - it's joined "in context"
Imagine I gave you just one of your sample rows from your expected output:
Paper 10 5
Promise I just copy pasted that.
What order is it from?
No idea.. You've lost the context, so it could be from any order. Rows are individual entities, that stand alone and without reference to any other row, as a set of data. This is why the same order info needs to appear on each row. A database could be made to produce the expected output you asked for, but it would be really quote complex in a low end database like sqlite. More important to me is to point out why there's a difference between what you thought the query would give you, and what it gave you, as I think that's the real problem: the query gave you what it was supposed to, there's no fault in it; it's more a faulty assumption of what you'd get
If you're trying to prepare a report that uses the order as some kind of header, select them individually in the front end app. Select ALL the orders, then one by one (order by order) pull all the item detail out, building the report as you go:
myorders = dbquery("SELECT * FROM ORDERS")
for each(order o in myorders)
print(o.header)
details = dbquery("SELECT * FROM dispatch_products where id_order = ?", o.id)
for each(detail d in details)
print(d.prod, d.qty, d.rate)
Here's a way to make the DB do it, but you'll need a version of SQLite that supports window functions (3.10 doesn't) or another db (SQLS > 2008, Oracle > 9, or other big-name db from the last 10 or so years, or a very recent MySQL):
SELECT
CASE WHEN rn = 1 THEN d.o_date END as o_date,
CASE WHEN rn = 1 THEN d.o_seller END as o_seller,
CASE WHEN rn = 1 THEN d.o_buyer END as o_buyer,
CASE WHEN rn = 1 THEN d.o_shipping END as o_shipping,
CASE WHEN rn = 1 THEN d.d_amount END as d_amount,
CASE WHEN rn = 1 THEN d.d_comm END as d_comm,
CASE WHEN rn = 1 THEN d.d_netAmount END as d_netAmount,
d.name,
d.qty,
d.rate
FROM
SELECT o.*, op.name, op.qty, op.rate, row_number() over(partition by o.id_order order by op.name, op.qty, op.rate) rn
FROM ORDERS o
INNER JOIN ORDERED_PRODUCTS op
ON o.id_order = op.id_order
WHERE o.buyer = 'abc'
) d
ORDER BY d.id_order, d.rn
We basically take your query, add on a row number that restarts every time order id changes, and only show data from the orders table where rownumber is 1. If your SQLite doesn't have row_number you can fake it: How to use ROW_NUMBER in sqlite which i'll leave as an exercise for the reader :)
I am relatively new to SQL and I will try to get the terminology correct. I have 2 tables, tbl_Trans which holds the general transaction details, and tbl_TransData which holds the details of the transaction.
I want to show each Trans record and the category of the trans which is held in the tbl_TransData. If there is more than one category for each Trans I want the text to be 'Mulitple', otherwise to return the category field
TRANS table content
int_Trans_ID dtm_TransDate txt_Type txt_Description txt_Bank dbl_Amount
1 17/12/2018 REC Sales Current 1000
2 20/12/2018 PAY Expenses paid Current -155
3 21/12/2018 PAY MW Repairs Current -250
TRANSDATA table content
int_TransData_ID int_TransID txt_Category dbl_Amount
1 1 Sales A -600
2 1 Sales B -400
3 2 Travel 100
4 2 Meal 55
5 3 MW Repairs 250
This is the code so far, but if I replace the ELSE 'Single' with ELSE txt_Category it does not work.
SELECT
int_Trans_ID,
dtm_TransDate AS Date,
txt_Type AS Type,
txt_Description AS Description,
(SELECT
CASE
WHEN count(int_TransID) > 1
THEN 'Multiple'
ELSE 'Single'
END
FROM
dbo.tbl_TransData TD
WHERE
TD.int_TransID = T.int_Trans_ID) AS Category
FROM
tbl_Trans T
GROUP BY
int_Trans_ID, dtm_TransDate, txt_Type, txt_Description
This is what I would like to see.
int_Trans_ID Date Type Description Category
1 2018-12-17 REC Sales Multiple
2 2018-12-20 PAY Expenses paid Multiple
3 2018-12-21 PAY Car Repairs MW Repairs
Sorry for the format of the tables.
Any help would be much appreciated, or even pointing me in the direction of other posts.
I would do:
with
x as (
select ins_trans_id, count(*) as cnt, max(txt_category) as cat
from transdata
group by ins_trans_id
)
select
t.int_trans_id,
t.dtm_transdate,
t.txt_type,
t.txt_description,
case when x.cnt = 0 then 'no category'
when x.cnt = 1 then x.cat
else 'Multiple' end as Category
from trans t
left join x on x.int_trans_id = t.int_trans_id
Please have a look at this,
I wrote subquery for case condition
SELECT
int_Trans_ID,
dtm_TransDate,
txt_type,
txt_Description,
CASE WHEN (SELECT COUNT(*) FROM tbl_Trans_Data td WHERE td.int_Trans_ID = t.int_Trans_ID)) > 1 THEN
'MULTİPLE'
ELSE
(SELECT Category from tbl_trans_data td Where td.int_Trans_ID = t.int_Trans_ID)
END AS Category
FROM
tbl_Trans t
I am working on a project in which I want to use Case to calculate price of product under specific Reference Number in SQL server. Below is my Sql query
SELECT
product AS Products,
refNum AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY
refNum, product
By Executing Above query I get:
Product Reference Count
Product1 Ref08 24
Product2 Ref08 7
Product3 Ref07 32
Product2 Ref12 1
Product3 Ref12 18
Product1 Ref07 76
Product1 Null 56
Can anyone guide me how to use Case statement in Sql query with group by statement to show price Below is the case:
if count < 10 then price 1
if count > 10 and < 100 then price 2
if count > 100 then price 3
I don't want to add a new table in my database. I hope you can understand my query.
Thanks in advance.
I think a basic CASE expression can handle your requirement:
SELECT
product AS Products,
refNum AS Refrence,
CASE WHEN COUNT(*) < 10 THEN 1
WHEN COUNT(*) >= 10 AND COUNT(*) < 100 THEN 2
ELSE 3 END AS price
FROM ProductPriceList
GROUP BY
product, refNum;
Not much to explain here, except that the 2 price case uses a bound which includes the count of 10 (since the 1 price case excludes it).
Here's alternative (doesn't differ much from exisiting one though):
You can use your query in subquery and use case outside:
select product,
--to get NULL values back
case Reference when 'RefNull' then NULL else Reference end [Reference],
case when [Count] < 10 then 1
when [Count] between 10 and 100 then 2
else 3 end [price]
from (
SELECT product AS Products,
--to allow also null values to be grouped
coalesce(refNum, 'RefNull') AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY coalesce(refNum, 'RefNull'), product
) [a]
Dataset:
Create Table ProductPriceList
(
Product varchar(10)
,RefNum CHAR(5)
,Records Int
);
Insert into ProductPriceList
Values
('Product1','Ref08',24)
,('Product2','Ref08',7)
,('Product3','Ref07',32)
,('Product2','Ref12',1)
,('Product3','Ref12',18)
,('Product1','Ref07',76)
,('Product1', NULL, 56);
With RCTE AS
(
Select Product
,RefNum
,Records
,1 RowNo
From ProductPriceList PPL
Union All
Select Product
,RefNum
,Records
,RowNo + 1
From RCTE R
Where RowNo + 1 < Records
)
Insert Into ProductPriceList (Product, RefNum, Records)
Select Product, RefNum, Records
From RCTE
where Records > 1
Query to fetch desired result:
Select Product
,RefNum
,Case When Count(*) < 10 Then 1
When Count(*) Between 10 and 99 then 2
Else 3 End Price
From ProductPriceList
Group By Product, RefNum
SQL Fiddle
Here are the key fields I'm working with: (They come from a join on two other tables and there are also some extra fields like date I'll be filtering on, but that stuff I can handle.)
Customer Type (text), Item ID (number), Sales $s (number), Customer ID (number)
I want to answer two questions with one query, if possible:
1) For a given list of customer type(s), what were the top 25 items (by sum of sales)
2) Using the list of 25 items generated in step 1, did a given list of customer IDs purchase each of the specified items?
So my final result would look something like this:
(header) Item # | Customer Purchased?
(row 01) Item 1123 | Yes
(row 02) Item 2452 | Yes
(row 03) Item 3354 | No
...
(row 25) Item 2554 | No
The item numbers would be listed in decreasing sales volume (within the specified customer category/categories) and I'd be testing whether sum of sales > 0 to trip the Yes / No flag on customer(s) purchased.
Thanks!
Assuming you have your columns in a table #Orders, and the "list of customer Ids" in a table #CustomerIds:
create table #Orders (CustomerId int, CustomerType varchar(10), ItemId int, Sales decimal);
create table #MyCustomers (CustomerId int);
... you could try something like this:
declare #CustomerType varchar(10) = 'Ugly';
with MarkedOrders as (
select
o.ItemId,
o.Sales,
case when mc.CustomerId is not null then 1 else 0 end IsMyCustomer
from
Orders o
left join #MyCustomers mc
on mc.CustomerId = o.CustomerId
where
o.CustomerType = #CustomerType
)
select top 25
o.ItemId,
max(IsMyCustomer) IsPurchasedByMyCustomer
from MarkedOrders o
group by o.ItemId
order by sum(o.Sales) desc