How to return a group of rows when one row meets "where" criteria in SQL Anywhere - where-clause

I am somewhat overwhelmed by what I am trying to do, since I have only been using SQL for 3 days now, but I already love the increased functionality over MS query. The need for the IN function is what drove me to learn about this, and I thank the community for the info here to get me through learning that.
I tried looking thru other questions, but I couldn't find one in which the intent was to group more than two rows, or to group a varying number of rows. This means that count and duplicate are both out as options.
What I am doing is analyzing a table of part number information that spans multiple store locations. The table gives a row to each instance of a part number, so if all 15 stores have some sort of history for a given part number, that part number will have 15 rows in the table.
I am wanting to look at other store's history for parts that meet the criteria of 0 sales history for my location. The purpose is to see if they can be transferred to another store instead of being returned to the vendor and incurring a restock fee.
Here is a simplified version of the table organized in the way I would want the output to be structured. I got here by having suspected part numbers and using the list of them as a text string in IN() but I want to go about this the other way and build a list of part numbers from sales data in this table.
Branch| Part_No| Description| Bin Qty|current 12 mo sales|previous 12 mo sales|
------|--------|------------|---------|-------------------|--------------------|
20 CA38385 SUPPORT 2 1 1
23 CA38385 SUPPORT 1 0 0
25 CA38385 SUPPORT 0 0 1
20 DFC10513 Hdw Kit 0 1 0
23 DFC10513 Hdw Kit 1 0 0
07 DFC10513 Hdw Kit 0 1 0
3 D59096 VALVE 0 0 12
5 D59096 VALVE 0 0 4
6 D59096 VALVE 4 6 12
8 D59096 VALVE 0 0 0
33 D59096 VALVE 11 14 18
21 D59096 VALVE 4 4 4
22 D59096 VALVE 0 0 0
23 D59096 VALVE 10 0 0
24 D59096 VALVE 0 0 0
25 D59096 VALVE 0 0 0
26 D59096 VALVE 2 2 0
1 TE67401 Repair Kit 1 1 2
21 TE67401 REPAIR KIT 1 3 0
22 TE67401 REPAIR KIT 0 1 0
I am branch 23, so the start of the query as I understand it would be
Select * from part_information
Group By part_number
Having IN(Branch) 23 and bin qty > 0 and current_12_mo_sales=0 and previous_12_mo_sales = 0
Can you point me down the right track? This table has approx. 200000 rows in it, so I really need to learn how to do this. I really don't see a better way.
Thank you in advance for your help and or criticism -Cody

Select * from part_information
where part_number not in (
select part_number from part_information
where branch = 23 and bin_qty > 0 -- etc...
)
(Apologies for lack of formatting).

This ended up working the way I wanted
SELECT pi_Branch, pi_Franchise, pi_Part_No, pi_Description, pi_Bin_Qty,
pi_Bin, pi_current_12_mo_sales, pi_previous_12_mo_sales, pi_Inventory_Cost,
pi_Return_Indicator
From Part_Information
Where pi_Part_No IN (Select pi_Part_No
From Part_Information
Where pi_Branch=23 And
pi_Bin_Qty>0 And pi_current_12_mo_sales<=0
And pi_previous_12_mo_sales<=0)
I was thinking that this had to be some complex process, but in reality, two simple queries were all that was needed.
I would still be interested in anyone's opinion on a better or more efficient way of handling this.
Thanks Mischa for getting me there!

Related

SQL : How to create a row per period value

I am currently trying to upskill myself within data analysis using tools such as SQL, EXCEL etc. So apologies, if what I am asking for may not make much sense, but happy to expand/clarify where required.
Problem :
I am trying to create a period by period line graph, showing pay across periods. However, with my current dataset the rows are :
employee codes and the columns are the individual periods with the values pertaining to that period for each row.
In order to achieve the requirements for my line graph. I would need to perform pivot of some sort to create a row per period for each worker. This will then allow me to group by periods for my line graph.
Current dataset :
Code Name Period 1 Period 2 Period 3
P1 Worker 1 2740.67 0 0
2 Worker 2 0 0 0
3 Worker 3 0 759.85 607.88
4 Worker 4 0 0 0
5 Worker 5 5000 5000 5000
6 Worker 6 1762.5 1672.5 960
12 Worker 7 6050 7750 5000
7 Worker 8 625.38 748.46 10
1234 Worker 9 2616.67 2616.67 2616.67
8 Worker 10 500 200 0
144 Worker 11 0 0 0
M100 Worker 12 423.08 0 0
M01 Worker 13 1583.33 1583.33 1583.33
M102 Worker 14 5833.33 5833.33 0
2403 Worker 15 8333.33 8333.33 11269.23
So for worker 5 they should have have 3 rows. The only thing i can think of is subqueries per worker that make up the columns or multiple unions, but seems rather time consuming ? Was hoping for a quicker efficient way of achieving what i need.

Calculating attrition in SQL

I am more or less noob to sql so I would really appreciate if anyone of you could give some hints how start to deal with the task below.
We have a database of donatons made by regular donors to an NGO.
Fields: donor_id, date
We need to crate an attrition table listing the donation periods and the proportion of donors who are still donating the organization after n months.
As we count donors from their first donation, the first period is 100%, than the request should check if the donor gave donation in the 2nd, 3rd Nth month after the donors's first donation.
Donation 1 2 3 4 5 6 7 8 9 10 11
donor 1 1 1 1 0 1 0 1 0 0 0 0
donor 2 1 1 0 0 0 1 0 0 1 0 0
donor 3 1 0 1 0 0 0 0 0 0 0 0
Any idea? :) Thank you!
PS: until know we used excel or google sheets for this but now we got a databse with 50 million rows, so I have been told to find a solution quickly.

How to Create a CDF out of a PDF in SQL

So I have a datatable that looks something like that following. ID represents an object, bin represents how I am segmenting the data, and percent is how much of a data falls into that bin.
id bin percent
2 8 0.20030698388
2 16 0.14504988488
2 24 0.12356101304
2 32 0.09976976208
2 40 0.09056024558
2 48 0.07137375287
2 56 0.04067536454
2 64 0.03914044512
2 72 0.02916346891
2 80 0.16039907904
3 8 0.36316695352
3 16 0.03958691910
3 24 0.11876075731
3 32 0.13253012048
3 40 0.03098106712
3 48 0.07228915662
3 56 0.07745266781
3 64 0.02581755593
3 72 0.02065404475
3 80 0.11876075731
I am looking for a function to turn this dataset into a cdf partitioning id. I have tried cume_dist and percent_rank, but they do not appear to work.
I am facing a similar problem and found this great tutorial for doing exactly that:
https://dwaincsql.com/2015/05/14/excel-in-t-sql-part-2-the-normal-distribution-norm-dist-density-functions/
It tries to rebuild the Excel function NORM.DIST function which gives you either the PDF if you set the cummulative flag as FALSE and the CDF if you set it as TRUE. I assumed that CUME_DIST would do the exact same thing in SQL. However, it turns out that the latter distributes by counting the elements whereas Excel uses the relative differences in the values.

TSQL -- Retrieve parent ID

The raw data in my table consists of an ID column and a column 'IsFolder' which can be 1 or 0, like this:
ID IsFolder
1 1
2 0
3 0
4 1
5 0
6 0
7 0
8 0
9 0
10 0
11 1
12 0
13 0
14 0
15 1
16 0
17 0
The way the code interprets this is that if a line has a 1 for 'IsFolder' then it is a Folder, and all of the tasks below it (until you hit the next Folder) are children of that folder.
What I'd like to have is a Select statement that will just return the ID of the parent folder for all non-folder tasks. So something like:
ID ParentFolder
2 1
3 1
5 4
6 4
7 4
8 4
9 4
10 4
12 11
13 11
14 11
16 15
17 15
I'm using MS SQL Server Management Studio 2005. I feel like this is an easy answer to those familiar with using cursors (which I am not). I can't think of any other way to do it but maybe someone else can. Anyway thanks in advance for any answers and sorry if I did something wrong, this is my first post.
You don't need a cursor for that - just a subquery:
SELECT ID,
(SELECT MAX(ID)
FROM Folders
WHERE ID < f.ID
AND IsFolder = 1) AS Parent
FROM Folders f
WHERE IsFolder = 0
I'd just like to point out that this task would be much easier, and the overall design much more extensible, if the structure of the data was changed a little. How are you going to add a task to folder 4, for example? If the parent and child relationship was extracted to two different tables, it might help.

Sql Server Row Concatenation

I have a table (table variable in-fact) that holds several thousand (50k approx) rows of the form:
group (int) isok (bit) x y
20 0 1 1
20 1 2 1
20 1 3 1
20 0 1 2
20 0 2 1
21 1 1 1
21 0 2 1
21 1 3 1
21 0 1 2
21 1 2 2
And to pull this back to the client is a fairly hefty task (especially since isok is a bit). What I would like to do is transform this into the form:
group mask
20 01100
21 10101
And maybe go even a step further by encoding this into a long etc.
NOTE: The way in which the data is stored currently cannot be changed.
Is something like this possible in SQL Server 2005, and if possible even 2000 (quite important)?
EDIT: I forgot to make it clear that the original table is already in an implicit ordering that needs to be maintained, there isnt one column that acts as a linear sequence, but rather the ordering is based on two other columns (integers) as above (x & y)
You can treat the bit as a string ('0', '1') and deploy one of the many string aggregate concatenation methods described here: http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/