Delphi sort by sum of three fields - delphi - delphi

I have a database (*.mdb), scheme of connection, that I use in my program:
TADOConnection -> TADOTable
DB has a table named Table1, which is connected by ADOTable. In Table1 there are fields A, B, C - floating point values. I need to sort the table by sums of these numbers.
For example:
Name A B C
------ --- --- ---
John 1 2 5
Nick 1 5 3
Qwert 1 5 2
Yuiop 2 3 1
I need to sort them, so the name, which A+B+C is bigger, would be first.
Sorted variant:
Name A B C
------ --- --- ---
Nick 1 5 3
John 1 2 5
Qwert 1 5 2
Yuiop 2 3 1
How to do this ?

While writing this, I understood what to do: I need a calculated field in the table, which is equal to A+B+C, and I must sort the table using it.

I do not have MS Access but with other Data Base Systems, I would use SQL to achieve this:
There are several SO answers along these lines for MS Access (try Microsoft Access - grand total adding multiple fields together)
So start with something like this:
Select Name, (A+B+C) as total, A, B, C
from table1
order by total desc

Related

MS Access: compare multiple query results from one table against the results of a query on the same table

I am building an ms access db to manage part numbers of mixtures. It’s pretty much a bill of materials. I have a table, tblMixtures that references itself in the PreMixture field. I set this up so that a mixture can be a pre-mixture in another mixture, which can in turn be a pre-mixture in another mixture, etc. Each PartNumber in tblMixture is related to many Components in tblMixtureComponents by the PartNumber. The Components and their associated data is stored in tblComponentData. I have put in example data in the tables below.
tblMixtures
PartNumber
Description
PreMixtures
1
Mixture 1
4, 5
2
Mixture 2
4, 6
3
Mixture 3
4
Mixture 4
3
5
Mixture 5
6
Mixture 6
tblMixtureComponents
ID
PartNumber
Component
Concentration
1
1
A
20%
2
1
B
40%
3
1
C
40%
4
2
A
40%
5
2
B
30%
6
2
D
30%
tblComponentData
ID
Name
Density
Category
1
A
1.5
O
2
B
2
F
3
C
2.5
I
4
D
1
F
I have built the queries needed to pull the information together for the final mixture and even display the details of the pre-mixtures and components used for each mixture. However, with literally tens of thousands of part numbers, there can be a lot of overlap in pre-mixtures used for mixtures. In other words, Mixture 4 can be used as a pre-mixture for Mixture 1 and Mixture 2 and a lot more. I want to build a query that will identify all possible mixtures that can be used as a pre-mixture in a selected mixture. So I want a list of all the mixtures that have the same components or subset of components as the selected mixtures. The pre-mixture doesn’t have to have all the components in the mixture, but it can’t have any components that are not in the mixture.
If you haven't solved it yet...
The PreMixtures column storing a collection of data is a sign that you need to "Normalize" your database design a little more. If you are going to be getting premixture data from a query then you do not need to store this as table data. If you did, you would be forced to update the premix data every time your mixtures or components changed.
Also we need to adress that tblMixtures doesn't have an id field. Consider the following table changes:
tblMixture:
id
description
1
Mixture 1
2
Mixture 2
3
Mixture 3
tblMixtureComponent:
id
mixtureId
componentId
1
1
A
2
1
B
3
1
C
4
2
A
5
2
B
6
2
D
7
3
A
8
4
B
I personally like to use column naming that exposes primary to foreign key relationships. tblMixtures.id is clearly related to tblMixtureComponenets.mixtureId. I am lazy so i would also probably abreviate everything too.
Now as far as the query, first lets get the components of mixture 1:
SELECT tblMixtureComponent.mixtureId, tblMixtureComponent.componentId
FROM tblMixtureComponent
WHERE tblMixtureComponent.mixtureId = 1
Should return:
mixtureId
componentId
1
A
1
B
1
C
We could change the WHERE clause to the id of any mixture we wanted. Next we need to get all the mixture ids with bad components. So we will build a join to compare around the last query:
SELECT tblMixtureComponent.mixtureId
FROM tblMixtureComponenet LEFT JOIN
(SELECT tblMixtureComponent.mixtureId,
tblMixtureComponent.componentId
FROM tblMixtureComponent
WHERE tblMixtureComponent.mixtureId = 1) AS GoodComp
ON tblMixtures.componentId = GoodComp.componentId
WHERE GoodComp.componentId Is Null
Should return:
mixtureId
2
Great so now we have ids of all the mixtures we don't want. Lets add another join to get the inverse:
SELECT tblMixture.id
FROM tblMix LEFT JOIN
(SELECT tblMixtureComponent.mixtureId
FROM tblMixtureComponenet LEFT JOIN
(SELECT tblMixtureComponent.mixtureId,
tblMixtureComponent.componentId
FROM tblMixtureComponent
WHERE tblMixtureComponent.mixtureId = 1) AS GoodComp
ON tblMixtures.componentId = GoodComp.componentId
WHERE GoodComp.componentId Is Null) AS BadMix
ON tblMixtures.id = BadMix.mixtureId
WHERE BadMix.mixtureId = Null AND tblMixture.id <> 1
Should return:
mixtureId
3
4
Whats left is all of the ids of that have similar components but not nonsimilar components to mixture 1.
Sorry i did this on a phone...

Rename SAS variables in merge

Suppose I have the following dataset lookup:
ID T001 T002 T002 T004 T005
1 0 1 2 3 4
2 1 2 3 4 5
And I want to merge this onto my main dataset main:
proc sql;
create table main as
select a.*, b.*
from main as a
left join lookup as b on a.ID = b.ID;
quit;
However, this will merge the variables at "T001", "T002", "T003" etc.
I am trying to rename the variables with the merge/join, without having to manually rename each of them as there are 100's of these variables in the dataset. I am looking to get something like
ID V1 V2 V3 V4 V5
1 0 1 2 3 4
2 1 2 3 4 5
You can change the variables names dynamically with a simple macro function after the join
data have;
input ID T001 T002 T003 T004 T005;
datalines;
1 0 1 2 3 4
2 1 2 3 4 5
;
%macro rn;
%do i = 1 %to 5;
T00&i. = V&i.
%end;
%mend;
proc datasets lib=work nolist;
modify have;
rename %rn;
run;quit;
EDIT:
data have;
array t T001-T586 (586*100);
run;
%macro rn;
%do i=1 %to 586;
T%sysfunc(putn(&i., z3.)) = V&i.
%end;
%mend;
proc datasets lib=work nolist;
modify have;
rename %rn;
run;quit;

Change the ordering of NULL values in all table columns postgresql call

I am using rails with postgresql to populate a dataTable and was wondering if there is a way to change the default behaviour of NULLS being the higher value (coming after large numbers when sorted) to become equivalent to lower than 0 in a sort. From what I understand this is a built in postgresql behaviour, so I think I will have to use the sql call to achieve this. And I need to apply this to all columns so it works with the DataTables sort ASC/DESC functionality.
Example some functionality similar to:
def get_raw_records
Analytics::Database.where(id: 7).order('give nulls < 0 value here for all columns?')
end
NULLS FIRST/ LAST does not give this functionality I need something like coalesce that ideally does not return a sorted instance but changes the default behaviour of nulls placed after large values when for it is sorted client side
you can use
order by coalesce(col_name,-1)
close to Sabari suggested:
db=# with c(v) as (values('1'),('a'),(null),(null),('b'))
select * from c
order by coalesce(v,'-infinity') asc;
v
---
1
a
b
(5 rows)
db=# with c(v) as (values('1'),('a'),(null),(null),('b'))
select * from c
order by coalesce(v,'-infinity') desc;
v
---
b
a
1
(5 rows)
instead of fixed integer below zero I use -inf here. which works fine with text (not because text understands infinity, but rather because - goes before [a-z] or [0-9]), but would not work with normal integer. Of course you can cast it to float:
db=# with c(v) as (values(1::float),(3),(null),(null),(-9))
select * from c
order by coalesce(v,'-infinity') desc;
v
----
3
1
-9
(5 rows)
db=# with c(v) as (values(1::float),(3),(null),(null),(-9))
select * from c
order by coalesce(v,'-infinity') asc;
v
----
-9
1
3
(5 rows)
with is dangerous (well, not in sorting though) itself (and ugly). which leads to the answer - I don't see good solution here from the top of my head... You should better make separate boundaries for different data types.
In Postgres you can specify in the order by clause how you want NULL sorted:
select 1 as col UNION select 2 UNION SELECT NULL ORDER BY col ASC NULLS FIRST;
You can either specify NULLS FIRST or NULLS LAST
See https://www.postgresql.org/docs/current/static/queries-order.html

SPSS Restructure Data

I have data in the following format:
ID Var1
1 a
1 a
1 b
1 b
2 c
2 c
2 c
I'd like to convert it (restructure it) to the following format in SPSS:
ID Var1_1 Var1_2 Var1_3 Total_Count
1 n(a)=2 n(b)=2 n( c )=0 4
2 n(a)=0 n(b)=0 n( c )=3 3
First I'll create some fake data to work with:
data list list/ID (f1) Var1 (a1).
begin data
1 a
1 a
1 b
1 b
2 c
2 c
2 c
3 b
3 c
3 c
3 c
end data.
dataset name ex.
Now you can run the following - aggregate, restructure, create the string with the counts:
aggregate outfile=* /break ID Var1/n=n.
sort cases by ID Var1.
casestovars /id=ID /index=var1.
recode a b c (miss=0).
string Var1_1 Var1_2 Var1_3 (a10).
do repeat abc=a b c/Var123=Var1_1 Var1_2 Var1_3/val="a" "b" "c".
compute Var123=concat("n(", val, ")=", ltrim(string(abc, f3))).
end repeat.
compute total_count=sum(a, b, c).
If you're doing this in SPSS Modeler, here is a stream image that works for this. The order is:
Create Data Set using User Input node, setting ID to integer and Var1 to string
Restructure by Var1 values to generate field Var1_a, Var1_b, and Var1_c
Aggregate using key field ID to sum counts Var1_a, Var1_b, and Var1_c, allowing Record Count field to be generated
Output to Table
Restructure and Aggregate in SPSS Modeler
The transpose node comes in handy if you use version 18.1.
As it is a simple pivot, you can go to "Fields and Records", then place the ID in "Index", Var1 in "Fields" and see if you can add another field for Count aggregation. If not, just derive it.

How to store word compositions in a relational database in a normalized way?

I'm trying to find a nice way to store word compositions of the following form:
exhaustcleaningsystem
exhaust cleaning system
exhaustcleaning system
exhaust cleaningsystem
The combinations are given by a default per case. Every word in a composition is stored as a unique row in table 'labels'.
labels
id value
--------------------------
1 exhaustcleaningsystem
2 exhaust
3 cleaning
4 system
5 exhaustcleaning
6 cleaningsystem
I thought about a new table called 'compositions':
compositions
id domain_id range
----------------------
1 1 2,3,4
2 1 5,4
etc...
But storing multiple separated values in a column isn't normalized design. Any ideas for that?
BTW: I'm using MySQL und ActiveRecord/Rails.
The design you propose is not even in first normal form, since range is not atomic
The schema I'd use here would be
compositions
id domain_id
-------------
1 1
2 1
compositions-content
composition_id rank label_id
------------------------------------------
1 1 2
1 2 3
1 3 4
2 1 5
2 2 4
with composition_id referencing an composition.id and label_id referencing label.id
The rank column is optional and should be here if and only if the range you define here is order-sensitive.
With this design, you have some referential integrity at DB level.
Well, this is as far as I can think of in terms of normalisation:
sets
id domain_id
--------------
1 1
2 1
etc...
compositions
id set_id label_id order
---------------------------
1 1 2 1
2 1 3 2
3 1 4 3
4 2 5 1
5 2 4 2
etc...

Resources