Django sum boolean fields horizontally - django-models

I have a django model that records multiple user preferences horizontally.
class Preferences(models.Model):
user = models.ForeignKey(CustomUser,on_delete='CASCADE')
choice1 = models.BooleanField()
choice2 = models.BooleanField()
choice3 = models.BooleanField()
choice4 = models.BooleanField()
choice5 = models.BooleanField()
I'm trying to achieve the SQL query of:
(select
(case when choice1 = True then 1 else 0 end) +
(case when choice2 = True then 1 else 0 end) +
(case when choice3 = True then 1 else 0 end) +
(case when choice4 = True then 1 else 0 end) +
(case when choice5 = True then 1 else 0 end) + as choice_sum
from Preferences)
How should I go about doing this in Django?
In case you want to know, I'm storing them horizontally as each user will have to record preferences for all choices which would increase in the future and I don't want multiple rows of unnecessary user FK.
Edit:
I realised my question might seem a bit weird. My objective is to eventually run a query that selects records where there is at least one True for any of the choices fields.

My objective is to eventually run a query that selects records where
there is at least one True for any of the choices fields.
Using Django filter + Q objects
from django.db.models import Q
.....
.....
choices = Preferences.objects.filter(Q(choice1=True) | Q(choice2=True) | Q(choice3=True) | Q(choice4=True) | Q(choice5=True))

Related

Updating one column based on parameter from another column in mssl1

Please I want to update my client database based on the job type
id Job_type Meal_Ticket
---------------------------
1 x 20
2 2x 12
Meaning if I click on add 20 meal tickets on button click, it should update to this:
id Job_type Meal_Ticket
----------------------------
1 x 40
2 2x 52
I tried
UPDATE Staff
SET Rticket = CASE
WHEN Jobtype = 'x' THEN Rticket = SUM(Rticket + 20)
WHEN Jobtype = '2x' THEN Rticket = SUM(Rticket + 2*20)
ELSE Rticket
END
I think you want this:
UPDATE Staff
SET Rticket = CASE WHEN Jobtype = 'x' THEN Rticket + 20
WHEN Jobtype = '2x' THEN Rticket + 40 END
WHERE Jobtype IN ('x', '2x');
The only problem I see with your logic is that you are using SUM to add two quantities, when you should just be using the + operator.

What is optimal number of tables we can use with JOINs?

I have a query which fetches records from 7 tables. All these tables are JOINed to get the details, few tables used multiple times with different ON clause. So there are 10 JOINs in the query. How can we optimize the query for getting better performance? We already have indexes on JOIN columns. Anything we can do to reduce the number of JOINs? Am using MS SQL 2012 with compatibility level 2008.
Query:
SELECT TOP 100
MT.ProjectId,
matRef,
matDescription,
matKeyDescription,
matOpenDate,
matUFN,
matBranchRef,
matClosedDate,
ERN1.feeRef,
WorkTypeCode,
DPT.deptNo AS matDeptRef,
PreviousRef,
MT.ApplicationID,
MatterCompleted,
CASE WHEN MLC.PFCivil_MatterCount = 0 THEN 0 ELSE 1 END AS IsCPF,
CASE WHEN MLC.PF_MatterCount = 0 THEN 0 ELSE 1 END AS IsPF,
CASE WHEN MLC.Family_MatterCount = 0 THEN 0 ELSE 1 END AS IsFM,
CASE WHEN MLC.WL_MatterCount = 0 THEN 0 ELSE 1 END AS IsWills,
CASE WHEN MLC.Convey_MatterCount = 0 THEN 0 ELSE 1 END AS IsConvey,
CASE WHEN MLC.Probate_MatterCount = 0 THEN 0 ELSE 1 END AS IsProbate,
CASE WHEN MLC.PI_MatterCount = 0 THEN 0 ELSE 1 END AS IsPi,
CASE WHEN MLC.PIPortal_MatterCount = 0 THEN 0 ELSE 1 END AS IsPiPortal,
CASE WHEN MLC.CM_MatterCount = 0 THEN 0 ELSE 1 END AS IsChest,
CASE WHEN MLC.Campaigns_MatterCount = 0 THEN 0 ELSE 1 END AS IsMarketing,
CASE WHEN MLC.PFFamilyFixedFee_MatterCount = 0 THEN 0 ELSE 1 END AS IsPFFamilyFixedFeeMatter,
ERN2.feeRef AS MatPartner,
MatPFCertificateNo,
CASE WHEN MT.matClosedDate = {d''1753-01-01''} THEN 0 ELSE 1 END AS IsArchived,
'''' Modules,
MT.ChargeDescID,
MT.MatterTypeID,
PrimaryClient.ClientName,
MB.LastAccDate,
MB.LastBillDate,
MB.LastClientDate,
MB.LastTimeDate
FROM dbo.Matter AS MT
JOIN dbo.Departments AS DPT ON DPT.deptID = MT.deptID
JOIN dbo.Earners AS ERN1 ON ERN1.MemberId = MT.MatFeeMemId
JOIN dbo.Earners AS ERN2 ON ERN2.MemberId = MT.matPartnerMemId
JOIN dbo.WorkTypes AS WT ON WT.WorkTypeID = MT.WorkTypeID
JOIN dbo.ivw_MatterLinkCount AS MLC ON MLC.ProjectId = MT.ProjectId
JOIN dbo.Banks AS ClientBank ON MT.matClientBank = ClientBank.bankID
JOIN dbo.Banks AS OfficeBank ON MT.matOfficeBank = OfficeBank.bankID
JOIN dbo.Banks AS DepositBank ON MT.matDepositBank = DepositBank.bankID
JOIN uvw_MatterPrimaryClient AS PrimaryClient ON PrimaryClient.ProjectId = MT.ProjectId
JOIN dbo.MatterBalance AS MB ON MT.ProjectId = MB.ProjectID
WHERE matDescription LIKE #Description
ORDER BY Isarchived, matRef
The trick here is that 'WHERE matDescription LIKE #Description' is not the real filter.
The real filter is 'TOP 100' together with 'ORDER BY Isarchived, matRef' because this filter will absolutely filter out anything but 100 rows.
So you need an index at Isarchived, matRef too. Table scan for matRef probably delays this one.
Also unless the Isarchived, matRef combination is unique by constraint, you better add the PK at the end like ORDER BY Isarchived, matRef, matid so there would be no extra problem picking the top 100.
Finally, if Isarchived is something like 0/1 and you have tons of records with 0 value it is useless at order by as there would always be 0. Set it as a filter Isarchived = 0 and remove it from order by - use matRef, matid and add a single index to matRef only.

How to create drop-down list in SSRS based on WHERE clause below?

At my organization we using UI third party tool that communicates with SQL database. I have access to a database, but not to the tool.
Based on a stored procedure below user able to choose from drop-down list DairyStatus "Open", "Closed", or "Both"
ALTER Procedure
AS
#ShowOpen bit = 0,
#ShowClosed bit = 0
SELECT
FROM
WHERE
AND
(
(CASE WHEN (#ShowOpen = 1) THEN
CASE WHEN (tblNoteRecipients.CompletedDate IS NULL and tblNoteRecipients.IsDiary = 1) or tblNoteRecipients.UserGUID is null THEN 1 ELSE 0 END
ELSE
1
END = 1)
AND
(CASE WHEN (#ShowClosed = 1) THEN
CASE WHEN (tblNoteRecipients.CompletedDate IS NULL) THEN 0 ELSE 1 END
ELSE
1
END = 1)
OR ((#ShowOpen = 1) AND (#ShowClosed = 1))
)
So my question is how can I make same drop-down list in SSRS?
What would be the data-set in order to populate this drop-down list?
create a parameter in ssrs with 3 static values(open closed both)
in where clause it should be something like :
( #DairyStatus = 'open' and ((tblNoteRecipients.CompletedDate IS NULL and tblNoteRecipients.IsDiary = 1) or tblNoteRecipients.UserGUID is null)) or
( #DairyStatus = 'closed' and tblNoteRecipients.CompletedDate IS not NULL) or
#DairyStatus = 'both'

Social Network Database Design - Friend/Block Relationships

I'm working on a social networking site and need users to be able to friend each other and/or block each other. The way I see it, 2 users can either be Friend, Pending, Block, or NULL. I'd like to have a single view that shows a single row for each confirmed relationship. My view properly shows the relationship but I had to do a workaround to only show 1 row/relationship without unioning the table with itself and swapping the order or Requestor and Requestee.
Anybody have any ideas about how to clean this up?
Thanks,
- Greg
Relationship Table:
Requestor (int) | Requestee (int) | ApprovedTimestamp (smalldatetime) | IsBlock (bit)
vwRelationship View:
SELECT DISTINCT
CASE WHEN f.Requestor < f.Requestee THEN f.Requestor ELSE f.Requestee END AS UserA,
CASE WHEN f.Requestor < f.Requestee THEN f.Requestee ELSE f.Requestor END AS UserB, CASE WHEN b.Requestor IS NULL AND b.Requestee IS NULL
THEN CASE WHEN f.AcceptedTimestamp IS NULL THEN 'Pending' ELSE 'Friend' END ELSE 'Block' END AS Type
FROM dbo.Relationship AS f LEFT OUTER JOIN
(SELECT Requestor, Requestee
FROM dbo.Relationship
WHERE (IsBlock = 1)) AS b ON f.Requestor = b.Requestor AND f.Requestee = b.Requestee OR f.Requestor = b.Requestee AND f.Requestee = b.Requestor
Example Query:
Select Type From vwRelationship Where (UserA = 1 AND UserB = 2) OR (UserA = 2 AND UserB = 1)
Scenario:
User 1 and User 2 don't know each other | Relationship Type = NULL
User 1 friends User 2 | Relationship Type = Pending
User 2 accepts | Relationship Type = Friend
a month later User 2 blocks User 1 | Relationship Type = Block
Here's what I ended up using:
Table - Relationship
RelationshipID, RelationshipTypeID, CreatedByUserID, CreatedTimestamp
Table - RelationshipType
RelationshipTypeID, RelationshipTypeName
Table - UserRelationship
UserID, RelationshipID, IsPending
Anybody think of anything better?

Need advice on denormalizing a database that deals with responses to polls

My web app deals with polls (surveys). Right now I have 2 tables as part of database schema.
polls
id
question
choices (ex: yes,no,maybe)
created
polls_responses
poll_id
user_id
tracker_id
response
The problem with this is that on some polls I have alot of responses (>1000). People can view the results of the polls and it will show how many users voted for yes, no, or maybe and how many anonymous users voted yes, no, or maybe. The problem with this is that whenever a user views the results of the poll, it has to loop through all the responses and count the total # of responses, # of responses for each choice, # of responses for each choice made by users, and # of responses for each choice made by tracker_id (anonymous users) and calculate percentages and display it in a bar graph. This makes the page load really slow. I was thinking of denormalizing the database to increase performance so that we have something like this
polls
id
question
choices (ex: yes,no,maybe)
total_responses (ex: 10,3,3,4)
user_responses (ex: 5,2,2,1)
anon_responses (ex: 5,1,3,1)
created
polls_responses
poll_id
user_id
tracker_id
response
That is, for the value in total_responses, the 10 is the total, 3 is the # of responses for choice yes, 3 is the # of responses for choice no, and 4 is the # of responses for choice maybe. The same format applies to user_responses and anon_responses fields. If I could get some opinions on this method, it would be greatly appreciated! Thanks for your time.
EDIT: I'm using MySQL
Firstly, I do not think you need to loop to count this.
Have a look at something like this
SELECT poll_id,
COUNT(response) Total,
SUM(CASE WHEN response = 'Y' THEN 1 ELSE 0 END) TotalYes,
SUM(CASE WHEN response = 'N' THEN 1 ELSE 0 END) TotalNo,
SUM(CASE WHEN response = 'M' THEN 1 ELSE 0 END) TotalMaybe,
SUM(CASE WHEN [user_id] IS NOT NULL AND response = 'Y' THEN 1 ELSE 0 END) UserYes,
SUM(CASE WHEN [user_id] IS NOT NULL AND response = 'N' THEN 1 ELSE 0 END) UserNo,
SUM(CASE WHEN [user_id] IS NOT NULL AND response = 'M' THEN 1 ELSE 0 END) UserMaybe,
SUM(CASE WHEN tracker_id IS NOT NULL AND response = 'Y' THEN 1 ELSE 0 END) TrackerYes,
SUM(CASE WHEN tracker_id IS NOT NULL AND response = 'N' THEN 1 ELSE 0 END) TrackerNo,
SUM(CASE WHEN tracker_id IS NOT NULL AND response = 'M' THEN 1 ELSE 0 END) TrackerMaybe
FROM polls_responses
GROUP BY poll_id
This should get you the respective results per poll_id, from where you can then join back to the table to retrieve the poll details.
Don't be afraid to use the database to do some heavy lifting for you. You don't have to loop through all the responses in your output.
You haven't specified your database platform, but you could probably handle this in the database using some joins and aggregate functions, or some sub-selects.

Resources