I have a Datagridview like this:
Model day1 day2 day3
car 1 2 4
bike 2 3 5
ship 6 1 7
Then i save it in my database table like this:
date model qty id
day1 car 1 1
day2 car 2 2
day3 car 4 3
day1 bike 2 4
day2 bike 3 5
day3 bike 5 6
day1 ship 6 7
day2 ship 1 8
day3 ship 7 9
Then using this query:
Select Min(id) As id,model From table Group By model order by id
i get the list of models in the same order as i had them in the datagridview:
car
bike
ship
The problem comes when i save 2 models with the same name in the table and then execute my query,i expect to get this:
1 car
2 bike
3 ship
4 car
but instead i get this:
1 car
2 bike
3 ship
The second proble with the current design i have is, if somehow i manage to retrieve the list as in the datagrid view:
car
bike
ship
car
How im going to know which quantities are from the first "car" and which ones are from the last "car" so i can put them in the datagridview back again.
In resume, i want to show in the datagrid the info in the same order i had it when i save it, but i dont know if the problem is the design of my table or the query im doing.
Example:
Saving this in my table, and then doing a query to get the same info in the same format:
Model day1 day2 day3
car 1 2 4
bike 2 3 5
ship 6 1 7
car 1 2 4
The problem is your query, you are grouping by the model
This means it will get the minimum Id of all the cars of that model, so you have car twice, but it only shows once because it groups all records of model car and selects the minimum Id which will be 1
Try this:
Select Count(id) As ModelCount,model From table Group By model order by id
on your dataset with the four cars and you will find that it will return the following:
ModelCount | model
2 | car
1 | bike
1 | ship
Based on your description, this is a gaps-and-island problem, sort-of. Actually, it is a data representation problem. Why are you storing the data with a single id instead of a row id and column id?
Given the way you are sorting the data, you can subtract a sequence to identify groups. Then you can group by and get the original rows:
select model
from (select t.*, row_number() over (partition by model order by id) as seqnum
from t
) t
group by model, (id - seqnum)
order by min(id);
But let me emphasize that if you want row/column information, then that is what you should be storing in the database.
Related
I'm attempting to have a function or view that is able to calculate and roll up various counts while being able to search on a many to many affiliation.
Here is an example data set:
Invoice Table:
InvoiceID LocationID StatusID
1 5 1
2 5 1
3 5 1
4 5 2
5 7 2
5 7 1
5 7 2
Group Table:
GroupID GroupName
1 Group 1
2 Group 2
GroupToLocation Table:
GroupToLocationID GroupID LocationID
1 1 5
2 2 5
3 2 7
I have gotten to the point where I could sum up the various statuses per location and get this:
LocationID Status1 Status2
5 3 1
7 1 2
Location 5 has 3 Invoices with a status of 1, and 1 invoice with a status of 2 while Location 7 has 1 status 1 and 2 status 2
There are two groups, and Location 5 is in both, while Location 7 is only in the second. I need to be able to set it up where I can append a where statement like this:
select * from vw_GroupCounts
where GroupName = 'Group 2'
or
select Invoice, SUM(*) from vw_GroupCounts
where GroupName = 'Group 2'
And that result in only getting Location 7. Whenever I do this, as I have to use left joins or something along those lines, the counts are duplicating for each group the the Location is affiliated with. I know I could do something along the lines of a subquery and pass in the GroupName into that, but the system I am working with uses a dynamic query builder that appends WHERE statements based on user input.
I don't mind using view, or functions, or any number of functions inside of functions, but I hope there is a way to do what I'm looking for.
Since locations 5 and 7 are in Group 2, if you search for group 2 in the where clause after joining all the tables, then you would get all records in this case, this isn't duplication, just the way the data is. A different join wouldn't change this, only changing the data. Let me know if I am misunderstanding something though.
Here is how you would join them to do that search.
Here it is with your first example of the location and status count.
I work on an Oracle database.
I have a table (it is a join table) but this is how it looks:
CustomerID days_attached Startdate enddate team
1 7 01-01-2016 08-01-2016 A
1 2 09-01-2016 10-01-2016 B
1 8 01-02-2016 09-02-2016 A
2 1 01-02-2017 02-02-2016 C
2 8 08-05-2017 16-05-2017 C
I need to know how long a person is attached to a specific team. A person can be attached to a person for a X amount of days. That person could be in a team. For instance in this case, how long is a person attached to team A = 7+8 15 days.
How do I get this in a SQL statement?
Our app only supports SQL not PL/sql .
I expect an output like:
CustomerID days_attached team
1 15 A
1 2 B
2 9 C
select customer, team, sum(dayattached) from table_name group by customer, team
hopefully this will help u
Ive been given some data in a spreadsheet which will soon be going into an automated import so i cannot do any manual entry on the spreadsheet. The data basically has the following columns. Trayid, trayname, itemdescription and rownumber. I didnt build these tables myself or i would of built it differently but i have to stick to the format which is already set.
The Data that is being imported will look at followed.
Trayid | Trayname | ItemDescription | RowNumber
1 Tray 1 Product 1 1
Product 2 2
Product 3 3
Product 4 4
2 Tray 2 Product 1 1
Product 2 2
Product 3 3
Product 4 4
Product 5 5
What i need to do is update the trayid and trayname for each of the other rows following row 1, so for example it will look like.
Trayid | Trayname | ItemDescription | RowNumber
1 Tray 1 Product 1 1
1 Tray 1 Product 2 2
1 Tray 1 Product 3 3
1 Tray 1 Product 4 4
2 Tray 2 Product 1 1
2 Tray 2 Product 2 2
2 Tray 2 Product 3 3
2 Tray 2 Product 4 4
2 Tray 2 Product 5 5
Im guessing i need to use a curser or something but im not sure, i think it can be done by going down the rownumbers and stopping when it see's rownumber 1 again and then carrying on with the next trayid and trayname.
Sorry if what i need doesnt make sense, it was awkward to explain.
SQL tables have no inherent ordering. So you cannot depend on that. But, there is something that you can do:
Define an identity column in the source table.
Create a view on the source table that excludes the identity.
Bulk insert into the view.
This will assign a sequential number to rows in the same order as the original data. Let's call this id. Then you can do your update by doing:
with toupdate (
select t.*,
max(TrayId) over (partition by grp) as new_TrayId,
max(TrayName) over (partition by grp) as new_TrayName
from (select t.*,
count(TrayId) over (order by id) as grp
from t
) t
)
update toupdate
set TrayId = new_TrayId,
TrayName = new_TrayName
where TrayId is null;
The idea is to define groups of rows corresponding to each tray. The simple idea is to count the number of non-NULL values before any given row -- everything in a group will then have the same grp value. Window functions then spread the actual value through all rows in the group (using max()), and these values are used for the update.
We have some tables in our database that pretty much grow infinitely so we are trying to create a task that will rollup old data on a periodic basis (probably daily) and remove the records that are contained in the rollup.
This is reasonably easy to do just using a GROUP BY. The catch is that are child tables that need to be rolled up as well and refer to the new completed parent table rows that they refer to and I have no idea how to do that without doing some really lame subqueries.
As an example say I start with the following data in the two tables:
Parent Table (ID is an IDENTITY column)
ID Type Amount
-- ---- ------
1 1 10.00
2 1 3.00
3 3 8.00
4 3 9.00
Child Table
ParentID Thing Qty
-------- ----- ---
1 8 3
1 6 6
2 8 4
2 5 3
3 8 2
3 5 1
4 5 4
First I would roll up the parent table into new rows that are grouped by Type and then the Amounts are summed together which would give the following:
ID Type Amount
-- ---- ------
5 1 13.00
6 3 17.00
The query to create the above data in Parent the query would look something like the following:
INSERT INTO Parent (Type, Amount)
SELECT Type, SUM(Amount) AS Amount
FROM Parent
GROUP BY Type
For the child table I want to do something similar, except grouping by "Thing" and summing Quantity with the ParentID referring to the newly created Parent that corresponds to the original Parent. This would create something like the following:
ParentID Thing Qty
-------- ----- ---
5 8 7
5 5 3
5 6 6
6 5 5
6 8 2
This query would look something similar to the following but I don't know how to get the ParentID or how to link to the Parent table:
INSERT INTO Child (ParentID, Thing, Qty)
SELECT ?, Thing, SUM(Qty) AS Qty
FROM Child
INNER JOIN Parent
ON ? = ?
GROUP BY ?, Thing
I would assume that this is something that happens somewhat frequently so does anyone know what the correct way to handle this situation is?
First Table:
Declare #max int = (Select MAX(ID) from parent)
Select #max
Select #max+R ID,type,Amount
from
(
Select type,sum(amount) 'Amount',ROW_NUMBER() over(order by type) 'R'
from parent
group by Type
) R
Second Table:
Select #max+TYPE 'ParentID',[group],sum(Qty) 'Qty'
from child
join parent
on id = parentid
group by type,[group]
order by [parentid],[group]
I am currently stuck on a problem where I have to write a SQL query to count the number of times a pair of items is ordered together.
The table that I have at my disposal is something like:
ORDER_ID | PRODUCT_ID | QUANTITY
1 1 10
1 2 20
1 3 10
2 1 10
2 2 20
3 3 50
4 2 10
I am looking to write a SQL query that can, for every unique pair of items, count the number of times they were ordered together and tell me the quantities when they were in the same order.
The resulting table should look like:
PRODUCT_ID_1 | PRODUCT_ID_2 | NUM_JOINT_ORDERS | SUM_QUANTITY_1 | SUM_QUANTITY__2
1 2 2 20 40
1 3 1 10 10
2 3 1 20 10
Some things to exploit are that:
Some orders only contain 1 item and so are not relevant in counting the pairwise relationship (not sure how to exclude these but maybe it makes sense to filter them first)
We only need to list the pairwise relationship once in the final table (so maybe a WHERE PRODUCT_ID_1 < PRODUCT_ID_2)
There is a similar post here, though I have reposted the question because
I really want to know the fastest way to do this since my original table is huge and my computational resources are limited, and
in this case I only have a single table and no table that lists the number.
You may use the following approach, which gives you the result shown above.
select
PRODUCT1, PRODUCT2, count(*), sum(QUANTITY1), sum(QUANTITY2)
from (
select
T1.PRODUCT_ID AS PRODUCT1,
T2.PRODUCT_ID AS PRODUCT2,
T1.QUANTITY AS QUANTITY1,
T2.QUANTITY AS QUANTITY2
from TABLE as T1, TABLE as T2
where T1.ORDER_ID=T2.ORDER_ID
and T1.PRODUCT_ID<T2.PRODUCT_ID
)
group by PRODUCT1, PRODUCT2