Apply Limit for a Condition - sql

I have a query that returns the credit notes (CN) and debit notes (DN) of an operation, each CN is accompanied by two or more DN (referenced by the field payment_plan_id). At the time of paging, for example I must bring 10 operations, that is 10 CN and their DN, but if I leave the limit at 10, it will also count the debit notes of the transaction that I must return in the query. So, it will only bring me 2, 3 or 4 operations depending on the number of DNs that accompany the credit note.
SELECT
value, installment, payment_plan_id, model,
creation_date, operation
FROM payment_plant
WHERE model != 'IMMEDIATE'
AND operation IN ('CN', 'DN')
AND creation_date BETWEEN '2017-06-12' AND '2017-07-12 23:59:59'
ORDER BY
model,
creation_date,
operation
LIMIT 10
OFFSET 1
Example of the table obviating some fields:
| id | payment_plan_id | value | installment | operation |
---------------------------------------------------------
| 1 | b3cdaede | 12 | 1 | NC |
| 2 | b3cdaede | 3.5 | 1 | ND |
| 3 | b3cdaede | 1.2 | 1 | ND |
| 4 | e1d7f051 | 36 | 1 | NC |
| 5 | e1d7f051 | 5.9 | 1 | ND |
| 6 | 00e6a0b4 | 15 | 1 | NC |
| 7 | 00e6a0b4 | 1 | 1 | ND |
| 8 | 00e6a0b4 | 3.6 | 1 | ND |
How can I limit the Limit so that it only consider the NCs?

Well, the query you give above doesn't do remotely what you describe. Assuming you actually want "the last 10 CN and their DN". You also don't explain what fields CN and DN have in common, so I'm going to assume that the fields are payment_plan_id and installment. Given that here's how you would get it:
WITH last_10_cn AS (
SELECT
value, installment, payment_plan_id, model,
creation_date
FROM payment_plant
WHERE model != 'IMMEDIATE'
AND operation = 'CN'
AND creation_date BETWEEN '2017-06-12' AND '2017-07-12 23:59:59'
ORDER BY
model,
creation_date,
operation
LIMIT 10
OFFSET 1 )
SELECT last_10_cn.*,
dn.value as dn_value, dn.model as dn_model,
dn.creation_date as dn_creation_date
FROM last_10_cn JOIN payment_plant as dn
ON last_10_cn.payment_plan_id = dn.payment_plan_id
AND last_10_cn.installment = dn.installment
ORDER BY
last_10_cn.model,
last_10_cn.creation_date,
last_10_cn.operation
dn.creation_date;
Adjust the above according to the actual join conditions and how you really want things to be sorted.
BTW, your table structure is what's giving you trouble here. DNs should really be a separate table with a foreign key to CNs. I realize that's not how most GLs do it, but the GL model predates relational databases.

Related

join two views and detect missing entries where the matching condition is in the next row of the other view/table (using SQLITE)

I am running a science test and logging my data inside two sqlite tables.
I have selected the data needed into two seperate and independent Views (RX and TX views).
Now I need to analyze the measurements and create a 3rd table view with the results with the following points in mind:
1- For each test at TX side (Table-1) there might be a corresponding entry at RX side (Table-2).
2- If the time stamp #RX side is less than the time stamp at the next row of the TX table view
we consider them to be associated with one record in the 3rd view/table and calculate the time difference OTHERWISE it would be a miss.
Question: How should i write the sql query in SQLITE to produce the analysis and test result given in table3?
Thanks a lot in advance.
TX View - Table (1)
id | time | measurement
------------------------
1 | 09:40:10.221 | 100
2 | 09:40:15.340 | 60
3 | 09:40:21.100 | 80
4 | 09:40:25.123 | 90
5 | 09:40:29.221 | 45
RX View -Table (2)
time | measurement
------------------------
09:40:15.7 | 65
09:40:21.560 | 80
09:40:30.414 | 50
Test Result View - Table (3)
id |TxTime |RxTime | delta_time(s)| delta_value
------------------------------------------------------------------------
1 | 09:40:10.221 | NULL |NULL | NULL (i.e. missed)
2 | 09:40:15.340 | 09:40:15.7 |0.360 | 5
3 | 09:40:21.100 | 09:40:21.560 |0.460 | 0
4 | 09:40:25.123 | NULL |NULL | NULL (i.e. missed)
5 | 09:40:29.221 | 09:40:30.414 |1.193 | 5
Use window function LEAD() to get the next time of each row in TX and join the views on your conditions:
SELECT t.id, t.time TxTime, r.time RxTime,
ROUND((julianday(r.time) - julianday(t.time)) * 24 * 60 *60, 3) [delta_time(s)],
r.measurement - t.measurement delta_value
FROM (
SELECT *, LEAD(time) OVER (ORDER BY Time) next
FROM TX
) t
LEFT JOIN RX r ON r.time >= t.time AND (r.time < t.next OR t.next IS NULL)
See the demo.
Results:
> id | TxTime | RxTime | delta_time(s) | delta_value
> -: | :----------- | :----------- | :------------ | :----------
> 1 | 09:40:10.221 | null | null | null
> 2 | 09:40:15.340 | 09:40:15.7 | 0.36 | 5
> 3 | 09:40:21.100 | 09:40:21.560 | 0.46 | 0
> 4 | 09:40:25.123 | null | null | null
> 5 | 09:40:29.221 | 09:40:30.414 | 1.193 | 5

Microsoft Access - Query - Most Recent Entries

I have a main table in Microsoft Access that consists of a document number "AD", a revision number "Rev" and a "Decision Date". There is occasionally more than 1 revision for every AD and 1-2 decision dates for every revision. I want to create a query that selects the most recent entry by decision date, and create a new table that only contains the most recent entries. The purpose of this new table is to have only unique ADs, so that AD can be made a primary key and related to other objects in the database.
Current Table: tbl1_Complete_Data
+----+--------+-----+---------------+
| ID | AD | Rev | Decision Date |
+----+--------+-----+---------------+
| 1 |98-24-02| 0 | 1998-06-20 |
| 2 |98-24-02| 0 | 1998-06-21 |
| 3 |98-24-02| 1 | 1998-06-24 |
| 4 |98-24-02| 1 | 1998-06-24 |
| 5 |98-24-03| 0 | 1998-06-24 |
| 6 |98-24-03| 0 | 1998-06-24 |
+----+--------+-----+---------------+
New Table: tbl2_Report_Data
+----+--------+-----+---------------+
| ID | AD | Rev | Decision Date |
+----+--------+-----+---------------+
| 3 |98-24-02| 1 | 1998-06-24 |
| 5 |98-24-03| 0 | 1998-06-24 |
+----+--------+-----+---------------+
^The goal of this table is to get rid of ID.
Consider:
SELECT tbl1_Complete_Data.* FROM tbl1_Complete_Data WHERE ID IN (
SELECT TOP 1 ID FROM tbl1_Complete_Data AS Dupe
WHERE Dupe.AD = tbl1_Complete_Data.AD ORDER BY Dupe.DecisionDate DESC, Dupe.ID);
Strongly advise not to use spaces nor punctuation/special characters in naming convention.

Returning singular row/value from joined table date based on closest date

I have a Production Table and a Standing Data table. The relationship of Production to Standing Data is actually Many-To-Many which is different to how this relationship is usually represented (Many-to-One).
The standing data table holds a list of tasks and the score each task is worth. Tasks can appear multiple times with different "ValidFrom" dates for changing the score at different points in time. What I am trying to do is query the Production Table so that the TaskID is looked up in the table and uses the date it was logged to check what score it should return.
Here's an example of how I want the data to look:
Production Table:
+----------+------------+-------+-----------+--------+-------+
| RecordID | Date | EmpID | Reference | TaskID | Score |
+----------+------------+-------+-----------+--------+-------+
| 1 | 27/02/2020 | 1 | 123 | 1 | 1.5 |
| 2 | 27/02/2020 | 1 | 123 | 1 | 1.5 |
| 3 | 30/02/2020 | 1 | 123 | 1 | 2 |
| 4 | 31/02/2020 | 1 | 123 | 1 | 2 |
+----------+------------+-------+-----------+--------+-------+
Standing Data
+----------+--------+----------------+-------+
| RecordID | TaskID | DateActiveFrom | Score |
+----------+--------+----------------+-------+
| 1 | 1 | 01/02/2020 | 1.5 |
| 2 | 1 | 28/02/2020 | 2 |
+----------+--------+----------------+-------+
I have tried the below code but unfortunately due to multiple records meeting the criteria, the production data duplicates with two different scores per record:
SELECT p.[RecordID],
p.[Date],
p.[EmpID],
p.[Reference],
p.[TaskID],
s.[Score]
FROM ProductionTable as p
LEFT JOIN StandingDataTable as s
ON s.[TaskID] = p.[TaskID]
AND s.[DateActiveFrom] <= p.[Date];
What is the correct way to return the correct and singular/scalar Score value for this record based on the date?
You can use apply :
SELECT p.[RecordID], p.[Date], p.[EmpID], p.[Reference], p.[TaskID], s.[Score]
FROM ProductionTable as p OUTER APPLY
( SELECT TOP (1) s.[Score]
FROM StandingDataTable AS s
WHERE s.[TaskID] = p.[TaskID] AND
s.[DateActiveFrom] <= p.[Date]
ORDER BY S.DateActiveFrom DESC
) s;
You might want score basis on Record Level if so, change the where clause in apply.

Pick a record based on a given value in postgres

I have a table in postgres like below,
alg_campaignid | alg_score | cp | sum
----------------+-----------+---------+----------
9829 | 30.44056 | 12.4000 | 12.4000
9880 | 29.59280 | 12.0600 | 24.4600
9882 | 29.59280 | 12.0600 | 36.5200
9827 | 29.27504 | 11.9300 | 48.4500
9821 | 29.14840 | 11.8800 | 60.3300
9881 | 29.14840 | 11.8800 | 72.2100
9883 | 29.14840 | 11.8800 | 84.0900
10026 | 28.79280 | 11.7300 | 95.8200
10680 | 10.31504 | 4.1800 | 100.0000
From which i have to select a record based on randomly generated number from 0 to 100.i.e first record should be returned if random number picked is between 0 and 12.4000,second if rendom is between 12.4000 and 24.4600,and likewise last if random no is between 95.8200 and 100.0000.
For Example
if the random number picked is 8 then the first record should be returned
or
if the random number picked is 48 then the fourth record should be returned
Is it possible to do this postgres if so kindly recommend a solution for this..
Yes, you can do this in Postgres. If you want to generate the number in the database:
with r as (
select random() * 100 as r
)
select t.*
from table t cross join r
where t.sum <= r.r
order by t.sum desc
limit 1;

SQL Storing Age Range

Im building an friendship site and I want to store restrictions for when a profile can be viewed.
Right now im using entity-attribute model to store restrictions. Examples of restrictions are what days a profile is available. The issue im having is i want to add a restriction on if a user can view a profile based on a users age range.
Im not sure if this approach is correct for storing, it feels really redundant but maybe im just being picky.
The two restrictions i want to add are minimum age and maximum age. Does this design seem like the correct approach?
User Attribute Entity Table
id(PK) | userid | attribute | entity
0 | 0 | 0 | 1
1 | 0 | 1 | 188
Attribute Table
id(PK) | attribute
0 | Minimum Age
1 | Maximum Age
2 | Contact Restricted Days
Entity Table
id(PK) | attribute_ID | Entity
0 | 0 | 18
1 | 0 | 19
.. | .. | ..
88 | 0 | 99
89 | 1 | 18
90 | 1 | 19
.. | .. | ..
188 | 1 | 99
199 | 2 | Monday
.. | .. | ..
205 | 2 | Sunday
I am posting this suggestion as an answer. But here is how I would have designed your table. Having id column in each table can cause headaches down the road, especially since you would need to explicitly define the column. Please compare the design below with your tables above:
User Attribute Entity Table
user_attr_entity_id(PK) | userid | attribute_id| entity_id
0 | 0 | 0 | 1
1 | 0 | 1 | 188
Attribute Table
attribute_id(PK) | attribute
0 | Minimum Age
1 | Maximum Age
2 | Contact Restricted Days
Entity Table
Entity_id(PK) | attribute_id | Entity_Value
0 | 0 | 18
1 | 0 | 19
.. | .. | ..
88 | 0 | 99
89 | 1 | 18
90 | 1 | 19
.. | .. | ..
188 | 1 | 99
199 | 2 | Monday
.. | .. | ..
205 | 2 | Sunday
UPDATE:
Seems like I must have misread your question initially. I think this design will work just fine. I tested using the query below:
SELECT userid
,a.attribute_id
,e.entity_id
,attribute
,entity_value
FROM user_attribute_entity_table uae
JOIN attribute_table a ON uae.attribute_id = a.attribute_id
JOIN entity_table e ON e.[entity_id] = uae.[entity_id]
If you're building for speed, i.e. if you need to optimize it for storing large amount of data, and if you know the "restrictions" (entitys) will not change a lot, then I'd say design it flatter/horizontally:
Id | UserId | Restriction1 | Restriction2 | Restriction3 | ..
This will however cost you flexibility, make it tougher on future growth/change and limit options.
Your original design is very flexible, and can be compared to a site with language dimensions - X amount of languages on Y amount of elements. Each element/entity should have it's own translation, and they should be easy to add/change.
However, design is somewhat about personal preference also. This is how I would solve it in a similar manner:
Users
-------------
UserId | Name
Attributes
-----------------------
AttributeId | Attribute
Entities
-----------------
EntityId | Entity/(or Value)
UserAttributeEntities
------------------------------------
Id | UserId (FK) | AttributeId (FK) | EntityId (FK)/or EntityValue
Entity, in my example, can either be it's own table (if values are resued often), or you can just put a column EntityValue direclty in the UserAttributeEntities table, and skip the Entities table.