Access SQL query group by - sql

I have a table with TaxID, Price, DatePurchaced
Every TaxId showning multiple times with different Price and DatePurchaced
I want to Group by TaxId with the Sum(Price) and show the last DatePurchaced
I also want a column with Count(TaxID)
I tryied ome queries but always show me one record the one with the latest datePurchaced

declare #tbl as table (TaxID int, Price money, DatePurchaced datetime)
insert into #tbl (TaxID, Price, DatePurchaced) values (1, 10.5, '2015-03-05 10:25:23');
insert into #tbl (TaxID, Price, DatePurchaced) values (1, 13, '2015-03-09 10:25:23');
insert into #tbl (TaxID, Price, DatePurchaced) values (1, 7, '2015-03-20 10:25:23');
insert into #tbl (TaxID, Price, DatePurchaced) values (2, 10.5, '2015-07-05 10:25:23');
insert into #tbl (TaxID, Price, DatePurchaced) values (2, 8, '2015-07-08 10:25:23');
select t.TaxId as TaxID,
count(t.TaxId) as Cnt,
sum(t.Price) as TotalPrice,
max(t.DatePurchaced) as LastPurchaseDate
from #tbl as t
group by t.TaxId

Related

Why it is showing No such column

/* Triggers*/
create table acustomer( id integer primary key, desc text, last_order_id integer);
create table bcustomer ( id integer primary key, item_id int, customer_id int, quan int, price int);
insert into acustomer (desc) values ( 'rohan');
insert into acustomer (desc) values ('mohan');
insert into acustomer (desc) values ('sohan');
select * from acustomer;
create trigger ccustomer after insert on bcustomer
begin
update acustomer set last_order_id = NEW.id where acustomer.id = NEW.customer_id;
end;
insert into bcustomer (item_id, customer_id, quan, price) values (1, 2, 3, 4);
insert into bcustomer (item_id, customer_id, quan, price) values (5, 6, 7, 8);
insert into bcustomer (item_id, customer_id, quan, price) values (8, 9, 10, 20);
insert into bcustomer (item_id, customer_id, quan, price) values (4, 12, 19, 13);
select * from acustomer;
select * from bcustomer;
#On executing insertion in table ccustomer, it is showing error : no such column : NEW.customer.id
Your last insert for bcustomer table is
insert into bcustomer (item_id, customer_id, quan, price) values (4, 12, 19, 13);
which doesn't have any matching last_order_id in acustomer.
If you will run
insert into bcustomer (item_id, customer_id, quan, price) values (4, 1, 19, 13);
customer_id = 1, it will update your acustomer table since it has a matching id, which is 1.
try this dbfiddle.

Find all records in a table where the most recent record in a join table has a column which is not equal to one is this table?

Image the tables:
CREATE TABLE items (
id INT,
price INT
);
CREATE TABLE item_price_history (
id INT,
item_id INT,
price INT
);
With the following data:
INSERT INTO items (id, price) VALUES (1, 199);
INSERT INTO items (id, price) VALUES (2, 159);
INSERT INTO items (id, price) VALUES (3, 129);
INSERT INTO items (id, price) VALUES (4, 119);
INSERT INTO item_price_history (id, item_id, price) VALUES (1, 1, 249);
INSERT INTO item_price_history (id, item_id, price) VALUES (2, 1, 239);
INSERT INTO item_price_history (id, item_id, price) VALUES (3, 1, 229);
INSERT INTO item_price_history (id, item_id, price) VALUES (4, 1, 199);
INSERT INTO item_price_history (id, item_id, price) VALUES (5, 2, 299);
INSERT INTO item_price_history (id, item_id, price) VALUES (6, 2, 259);
INSERT INTO item_price_history (id, item_id, price) VALUES (7, 2, 159);
INSERT INTO item_price_history (id, item_id, price) VALUES (8, 2, 109);
INSERT INTO item_price_history (id, item_id, price) VALUES (9, 3, 129);
INSERT INTO item_price_history (id, item_id, price) VALUES (10, 4, 159);
INSERT INTO item_price_history (id, item_id, price) VALUES (11, 4, 119);
INSERT INTO item_price_history (id, item_id, price) VALUES (13, 4, 99);
Now I would like to find all the items for which the items.price is not equal to the most recent item_price_history.price (id DESC) in item_price_history. In this case that should produce item with id 3 and 4. As their prices does NOT match the most recent price in item_price_history.
I did the following which works:
SELECT items.id, items.price i_price, item_price_history.id, item_price_history.price as ih_price
FROM items
LEFT JOIN item_price_history ON item_price_history.item_id = items.id
AND item_price_history.id = (SELECT MAX(id) FROM item_price_history WHERE item_id = items.id)
WHERE items.price != item_price_history.price
LIMIT 100
However I have a table of about 2 million rows in items and 20 million rows in item_price_history which I need to scan through, so performance is important.
How would I write such a query in a more performant way e.g by using DISTINCT ON or something?
https://www.db-fiddle.com/f/wPkdHvvzS2tmZq2vKUwgNi/2
Here is a query to do it in bulk with DISTINCT ON:
SELECT items.id, items.price i_price, item_price_history.id, item_price_history.price as ih_price
from items
join (select distinct on (item_id) id, item_id, price from item_price_history order by item_id desc, id desc) item_price_history
on item_price_history.item_id = items.id
WHERE items.price != item_price_history.price;
It should be well supported by an index on item_price_history (item_id , id, price); which will let it do a presorted index-only scan.

Firebird and SQL Server delete highest rows in groups

I need to delete the 3rd and greater records, sorted by product, type and display order, from the following tables:
Stockist table:
CREATE TABLE INVENTORYWEBSTOCKISTS
(
STOCKISTID NUMERIC(10,0) NOT NULL,
PRODUCTID NUMERIC(10,0) NOT NULL,
DISPLAYORDER NUMERIC(10,0),
CUSTOMERID NUMERIC(10,0),
CONSTRAINT PK_INVENTORYWEBSTOCKISTS PRIMARY KEY (STOCKISTID)
);
STOCKISTID is the unique autoinc column for the table and can be used as an ID. PRODUCTID and CUSTOMERID both reference other tables.
Customer table:
CREATE TABLE CUSTOMERS
(
CUSTOMERID NUMERIC(10,0) NOT NULL,
WEBSTOCKISTSTOCKISTTYPE VARCHAR(100),
CONSTRAINT PK_CUSTOMERS PRIMARY KEY (CUSTOMERID)
);
Customers table has records:
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (1, 'Reseller');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (2, 'Reseller');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (3, 'Reseller');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (4, 'Installer');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (5, 'Installer');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (6, 'Installer');
insert into CUSTOMERS (CUSTOMERID, WEBSTOCKISTSTOCKISTTYPE) values (7, 'Installer');
Stockist table has records:
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (1, 1, -100, 1);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (2, 1, -101, 2);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (3, 1, -102, 3);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (4, 1, -103, 4);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (5, 1, -104, 5);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (6, 1, -105, 6);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (7, 1, -106, 7);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (10, 2, -107, 3);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (13, 2, -108, 6);
insert into INVENTORYWEBSTOCKISTS (STOCKISTID, PRODUCTID, DISPLAYORDER, CUSTOMERID) values (14, 2, -109, 7);
For the combined results:
select
INVENTORYWEBSTOCKISTS.STOCKISTID,
INVENTORYWEBSTOCKISTS.PRODUCTID,
INVENTORYWEBSTOCKISTS.DISPLAYORDER,
CUSTOMERS.WEBSTOCKISTSTOCKISTTYPE
from
INVENTORYWEBSTOCKISTS
left join
CUSTOMERS on CUSTOMERS.CUSTOMERID = INVENTORYWEBSTOCKISTS.CUSTOMERID
order by
INVENTORYWEBSTOCKISTS.PRODUCTID,
CUSTOMERS.WEBSTOCKISTSTOCKISTTYPE,
INVENTORYWEBSTOCKISTS.DISPLAYORDER
Output:
STOCKISTID, PRODUCTID, DISPLAYORDER, WEBSTOCKISTSTOCKISTTYPE
7, 1, -106, Installer
6, 1, -105, Installer
5, 1, -104, Installer
4, 1, -103, Installer
3, 1, -102, Reseller
2, 1, -101, Reseller
1, 1, -100, Reseller
14, 2, -109, Installer
13, 2, -108, Installer
10, 2, -107, Reseller
I need to delete the 3rd and above record for each product/stockist type group ordered by display order, so would expect it to delete rows 5, 4, and 1.
I have tried heaps of different queries from here and the web generally, I can't find anything that will group and order for the delete and work on both MS SQL and Firebird 1.5.
SQL Fiddle to experiment with: http://sqlfiddle.com/#!3/7101de/1
So after deleting, the table should look like:
Output:
STOCKISTID, PRODUCTID, DISPLAYORDER, WEBSTOCKISTSTOCKISTTYPE
7, 1, -106, Installer
6, 1, -105, Installer
3, 1, -102, Reseller
2, 1, -101, Reseller
14, 2, -109, Installer
13, 2, -108, Installer
10, 2, -107, Reseller
The delete should be executed as one query, so I can pass it to the server.
*** Edit:
Maybe to simplify, if I can do a select command that returns the STOCKISTID's to be deleted, I can then execute the delete commands seperately.
*** Edit 2:
As a test, I added the stockist type field to the INVENTORYWEBSTOCKISTS table, and can run this query:
SELECT INVENTORYWEBSTOCKISTS.STOCKISTID
FROM INVENTORYWEBSTOCKISTS IWS1
WHERE
(SELECT COUNT(*)
FROM INVENTORYWEBSTOCKISTS IWS2
WHERE IWS2.PRODUCTID = IWS1.PRODUCTID
AND IWS2.STOCKISTTYPE = IWS1.STOCKISTTYPE
AND IWS2.DISPLAYORDER <= IWS1.DISPLAYORDER) > 2
and return the correct fields (ie the ones that should be deleted). This was based on a question asked previously on SO.
As soon as I try and link in the CUSTOMER table as the query should be, it gives different results, less rows. Maybe someone might be able to help with that?
Try this, I have used ROW_NUMBER to eliminate your case (From what I understood from your question)
;WITH CTE AS(
SELECT ROW_NUMBER()OVER(PARTITION BY PRODUCTID,WEBSTOCKISTSTOCKISTTYPE
ORDER BY (SELECT 1) )SNO, INVENTORYWEBSTOCKISTS.*,
CUSTOMERS.WEBSTOCKISTSTOCKISTTYPE FROM
INVENTORYWEBSTOCKISTS
LEFT JOIN
CUSTOMERS ON INVENTORYWEBSTOCKISTS.CUSTOMERID = CUSTOMERS.CUSTOMERID
)
SELECT * FROM CTE WHERE SNO <3
Edit: From your comments:
;WITH CTE AS(
SELECT ROW_NUMBER()OVER(PARTITION BY PRODUCTID,WEBSTOCKISTSTOCKISTTYPE
ORDER BY (SELECT DISPLAYORDER) )SNO, INVENTORYWEBSTOCKISTS.*,
CUSTOMERS.WEBSTOCKISTSTOCKISTTYPE FROM
INVENTORYWEBSTOCKISTS
LEFT JOIN
CUSTOMERS ON INVENTORYWEBSTOCKISTS.CUSTOMERID = CUSTOMERS.CUSTOMERID
)
SELECT STOCKISTID FROM CTE WHERE SNO>2
If it is a problem with CTE
DELETE FROM INVENTORYWEBSTOCKISTS WHERE STOCKISTID IN (
SELECT STOCKISTID FROM (
SELECT ROW_NUMBER()OVER(PARTITION BY PRODUCTID,WEBSTOCKISTSTOCKISTTYPE
ORDER BY (SELECT DISPLAYORDER) )SNO, INVENTORYWEBSTOCKISTS.*,
CUSTOMERS.WEBSTOCKISTSTOCKISTTYPE FROM
INVENTORYWEBSTOCKISTS
LEFT JOIN
CUSTOMERS ON INVENTORYWEBSTOCKISTS.CUSTOMERID = CUSTOMERS.CUSTOMERID
) AS A WHERE SNO>2
)

how to get Related Records using LINQ

Hello I have this table structure:
**ProductsTable**
ProductID
ProductName
**CategoriesTable**
CategoryID
CategoryName
**ProductCategories**
ProductID
CategoryID
Each Product can belong to multiple categories. Now I need a way to find Related Products. But I want it in this way:
Let's say Product1 belong to Laptop, Accessories. So only those products who belong to both categories (not just one) can be retrieved.
SQL Query will work, however if you can give LINQ it will be best.
Thanks in Advance
Marc V.
Update
Here is my sql solution with setup:
declare #p table(id int, name varchar(10))
declare #c table(id int, name varchar(10))
declare #pc table(pid int, cid int)
insert into #p (id, name) values (1, 'laptop')
insert into #p (id, name) values (2, 'desktop')
insert into #p (id, name) values (3, 'milk')
insert into #c (id, name) values (1, 'computer')
insert into #c (id, name) values (2, 'device')
insert into #c (id, name) values (3, 'food')
insert into #pc (pid, cid) values (1, 1)
insert into #pc (pid, cid) values (1, 2)
--insert into #pc (pid, cid) values (1, 3)
insert into #pc (pid, cid) values (2, 1)
insert into #pc (pid, cid) values (2, 2)
insert into #pc (pid, cid) values (3, 3)
declare #productId int;
set #productId = 1;
select *
from #p p
where
--count of categories that current product shares with the source product
--should be equal to the number of categories the source product belongs to
(
select count(*)
from #pc pc
where pc.pid = p.id
and pc.cid in (
select cid from #pc pc
where pc.pid = #productId
)
) = (select count(*) from #pc pc where pc.pid = #productId)
and
p.id <> #productId

Sql Server query with date filter

I have a table like this;
ID int,
OrderedDate DateTime
I want to select only records of followed month.
For example result set:
ID OrderedDate
110 January
110 February
200 January
200 February
How can I write this query?
I think you want list of months that ID has orders in but with the months sorted by the month number instead of the name?
create table test21210
(
id int,
OrderedDate datetime
)
go
insert test21210 (id, OrderedDate) values (110, '1/1/2010')
insert test21210 (id, OrderedDate) values (110, '1/5/2010')
insert test21210 (id, OrderedDate) values (110, '1/10/2010')
insert test21210 (id, OrderedDate) values (110, '2/2/2010')
insert test21210 (id, OrderedDate) values (110, '2/4/2010')
insert test21210 (id, OrderedDate) values (110, '2/6/2010')
insert test21210 (id, OrderedDate) values (200, '1/3/2010')
insert test21210 (id, OrderedDate) values (200, '1/5/2010')
insert test21210 (id, OrderedDate) values (200, '1/7/2010')
insert test21210 (id, OrderedDate) values (200, '1/9/2010')
insert test21210 (id, OrderedDate) values (200, '2/3/2010')
insert test21210 (id, OrderedDate) values (200, '2/5/2010')
insert test21210 (id, OrderedDate) values (200, '2/7/2010')
insert test21210 (id, OrderedDate) values (200, '2/9/2010')
go
with idmonth (id, MonthNumber) as
(
select id, MONTH(ordereddate) as 'MonthNumber'
from test21210
group by id, MONTH(ordereddate)
)
select id, DATENAME(MONTH, STR(MonthNumber)+'/1/2000')
from idmonth
order by id, MonthNumber
The question seems a bit unclear. But the example makes it look like you are wanting to sort by ID then by month name. If so, then I think this will do it. I don't have SQL Server to test it, so I'm sure it has syntax or other errors.
SELECT ID, DATENAME(month, OrderedDate) AS OrderedDate from table
ORDER BY 1, MONTH( OrderedDate )