How to perform multiple AND/OR meta_query using using $wpdb - sql

SCENARIO: I have a custom post type with start and end dates saved as post meta. This is to allow the admin to schedule dates to show AND hide a post. There is also the option to leave these dates blank, in which case the post just shows by default. As meta_query doesn't appear to allow you to perform an AND/OR comparison, I've dabbled with creating a custom SQL query using $wpdb. SQL is new territory for me. Currently, this works for the start date:
$today = date('Y-m-d');
$results = $wpdb->get_results($wpdb->prepare("
SELECT
$wpdb->posts.post_title,
$wpdb->posts.ID,
$wpdb->posts.post_content
FROM
$wpdb->posts,
$wpdb->postmeta
WHERE
$wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->posts.post_type = 'announcements'
AND ($wpdb->postmeta.meta_key = 'sap_start_date'
AND ($wpdb->postmeta.meta_value <= '$today' OR $wpdb->postmeta.meta_value = ''))
"));
However, when I try and amend the above to query the end date, I get nothing back. I tried changing the WHERE section to:
WHERE
$wpdb->posts.ID = $wpdb->postmeta.post_id
AND $wpdb->posts.post_type = 'announcements'
AND ($wpdb->postmeta.meta_key = 'sap_start_date'
AND ($wpdb->postmeta.meta_value <= '$today' OR $wpdb->postmeta.meta_value = ''))
AND ($wpdb->postmeta.meta_key = 'sap_end_date'
AND ($wpdb->postmeta.meta_value >= '$today' OR $wpdb->postmeta.meta_value = ''))
This returns an empty array.
QUESTION: How would I write this query to check both the sap_start_date and sap_end_date post meta values?

I figured out my problem was that I was using a logical AND against the same meta key object twice; how can postmeta.meta_key be equal to start_date and end_date? Using an answer from this SO question I managed to re-write the query to use aliases so that I could get the postmeta twice and query the two different keys:
SELECT
$wpdb->posts.post_title,
$wpdb->posts.ID,
$wpdb->posts.post_content
FROM
$wpdb->posts,
$wpdb->postmeta AS postmeta1,
$wpdb->postmeta AS postmeta2
WHERE
$wpdb->posts.ID = postmeta1.post_id
AND $wpdb->posts.ID = postmeta2.post_id
AND $wpdb->posts.post_type = 'announcements'
AND (postmeta1.meta_key = 'sap_start_date'
AND (postmeta1.meta_value <= '$today' OR postmeta1.meta_value = ''))
AND (postmeta2.meta_key = 'sap_end_date'
AND (postmeta2.meta_value >= '$today' OR postmeta2.meta_value = ''))
This works, although I'm still a little fuzzy on just how it works. If anyone could shed some further light on this purely for educational purposes it would be much appreciated.

Related

I am trying to convert Oracle view into SQL, but i am having issue with query performance

Oracle
(TO_CHAR(P.EstimatedInServiceDate, 'YYYY') =
(SELECT SUBSTR(ConfigurationValue, -4)
FROM PETE.vw_Configuration
WHERE configurationkey = 'CurrentPATYear'))
SQL - I tried to convert above code it is returning a data fine but my query is taking too long to run because of this particular chunk. If any better way to do this please let me know.
(Cast(DatePart(Year,P.EstimatedInServiceDate)as varchar) =
(SELECT right(ConfigurationValue, 4)
FROM Configuration
WHERE configurationkey = 'CurrentPATYear'))
You can use datepart() only :
where datepart(year, P.EstimatedInServiceDate) = (SELECT right(ConfigurationValue, 4)
FROM Configuration
WHERE configurationkey = 'CurrentPATYear')
)
It's a poor practice in SQL Server (or Oracle) to apply expressions to table columns in a WHERE-clause, as it makes the expression non-Sargable.
Instead write this something like:
P.EstimatedInServiceDate >=
(SELECT ConfigurationValue
FROM Configuration
WHERE configurationkey = 'CurrentPATYear')
and
P.EstimatedInServiceDate < dateadd(year,1,
(SELECT ConfigurationValue
FROM Configuration
WHERE configurationkey = 'CurrentPATYear'))

Trying to get better at understand sql queries

I'm a new developer in a corporate IT group. I feel completely lost looking at alot of the sql that's written in our code. There are many queries that are literally hundreds of lines long. Here's an example of a "smaller" one (the table/field names have been modified, but the structure is the same). Do I just suck at this or is it really difficult to understand? How would you approach rewriting it to be more manageable/understandable?
SELECT pd.commission_header_id COMMISSION_HEADER_ID
,pd.sales_rep_id DIRECT_SALESREP_ID
,pd.org_id ORG_ID
,LEAST(100, innview.spilt_percent) SPLIT_PCT
,pd.source SOURCE
,pd.application APPLICATION
,pd.plan PLANE
,pd.pay_freq pay_freq
,pd.emp_app_count EMP_APP_COUNT
,pd.client_name CLIENT_NAME
,pd.fed_id FED_ID
,pd.off_nbr OFF_NBR
,pd.payroll_num payroll_num
,TO_DATE(pd.product_start_date,'DD-MON-YY') PRODUCT_START_DATE
,pd.loss_date LOSS_DATE
,pd.acquisitions_ind ACQUISITIONS_IND
,pd.source_of_business SOURCE_OF_BUSINESS
,pd.prev_br_clt_nbr PREV_BR_CLT_NBR
,pd.previous_method PREVIOUS_METHOD
,pd.natl_acct_number NATL_ACCT_NUMBER
,pd.product_name PRODUCT_NAME
,pd.lost_reason LOST_REASON
,pd.client_id CLIENT_ID
,pd.lead_nbr LEAD_NBR
,pd.processed_date PROCESSED_DATE
,pd.rep_type REP_TYPE
,pd.order_number ORDER_NUMBER
,pd.conversion_type CONVERSION_TYPE
,SUBSTR(original_billing_info,1,INSTR(original_billing_info,'|',1,1)-1) BILLING_APPLICATION
,SUBSTR(original_billing_info,INSTR(original_billing_info,'|',1,1)+1,INSTR(original_billing_info,'|',1,2)-INSTR(original_billing_info,'|',1,1)-1) BILLING_CODE
,SUBSTR(original_billing_info,INSTR(original_billing_info,'|',1,2)+1,INSTR(original_billing_info,'|',1,3)-INSTR(original_billing_info,'|',1,2)-1) BILLING_PROD_GRP_NM
,SUBSTR(original_billing_info,INSTR(original_billing_info,'|',1,3)+1) BILLING_FIELD_FOR_CHRGS
,SUBSTR(original_discount_info,1,INSTR(original_discount_info,'|',1,1)-1) DISCOUNT_APPLICATION
,SUBSTR(original_discount_info,INSTR(original_discount_info,'|',1,1)+1,INSTR(original_discount_info,'|',1,2)-INSTR(original_discount_info,'|',1,1)-1) DISCOUNT_CODE
,CASE WHEN (NVL(innview.trans,0)) = 0
THEN 0
ELSE ( NVL(innview.comm,0)) / ( NVL(innview.trans,0))
END ORIGINAL_COMM_PCT
,pd.record_type RECORD_TYPE
,innview.trans PAR_SUM
,NVL(ocp.oic_clients_pk, pxmis.oic_client_products_pk_seq.nextval) CLIENT_PRODUCT_ID
,pd.associated_with ASSOCIATED_WITH_ID
,pd.refferal_sale refferal_sale
,pd.parent_client_nbr PARENT_CLIENT_NBR
FROM pxmis.pd_commissions pd
JOIN pxmis.oic_lookback_months olm ON (pd.application = olm.application
AND pd.plan = olm.plan)
LEFT OUTER JOIN pxmis.oic_client_products ocp ON (pd.off_nbr = ocp.off_nbr
AND pd.payroll_num = ocp.payroll_num
AND pd.application = ocp.application
AND pd.plan = ocp.plan
AND pd.sales_rep_id = ocp.direct_salesrep_id
AND pd.source = ocp.source
AND ocp.record_type in (:1,:2)
AND NVL(pd.refferal_sale,'NON REF') = NVL(ocp.refferal_sale,'NON REF'))
JOIN (SELECT SUM(NVL(transaction_amount,0)) as trans
,SUM(commission_amount) as comm
,SUM(pd2.oic_split_percent) as spilt_percent
,pd2.application as application
,pd2.plan as code
,pd2.sales_rep_id as sales_rep_id
,pd2.payroll_num as client_nbr
,LPAD(pd2.off_nbr,4,0) as off_nbr
FROM pxmis.pd_commissions pd2
JOIN pxmis.oic_lookback_months olm2 ON (pd2.application = olm2.application
AND pd2.plan = olm2.plan)
WHERE CASE WHEN (pd2.record_type IN ('SAPBA','ASAPBA'))
THEN pd2.SUB_RECORD_TYPE
ELSE 'Eligible'
END = 'Eligible'
AND pd2.record_type IN ('SDBDA', 'ASDBDA',
decode(:3,'CHCST','SAPBA',NULL),
decode(:4,'CHCST','ASAPBA',NULL),
'SAPBP','ASAPBP')
AND pd2.processed_date BETWEEN ADD_MONTHS(:5,(olm2.lookback_months_high - 1) * -1) AND ADD_MONTHS(:6, (olm2.lookback_months_low - 2) * -1) - 1
and :7 between olm2.effective_start_date and olm2.effective_end_date
and olm2.function_type = :8
GROUP BY pd2.application
,pd2.plan
,pd2.sales_rep_id
,pd2.payroll_num
,LPAD(pd2.off_nbr,4,0)) innview on (innview.application = pd.application
AND innview.code = pd.plan
AND innview.sales_rep_id = pd.sales_rep_id
AND innview.client_nbr = pd.payroll_num
AND innview.off_nbr = LPAD(pd.off_nbr,4,0))
WHERE :9 BETWEEN olm.effective_start_date AND olm.effective_end_date
AND pd.sales_rep_id <> -3
AND pd.record_type IN ('SAPBP','ASAPBP')
AND NOT EXISTS(SELECT 'X'
FROM pxmis.pd_commissions pd3
WHERE pd3.application = pd.application
AND pd3.plan = pd.plan
AND pd3.sales_rep_id = pd.sales_rep_id
AND pd3.payroll_num = pd.payroll_num
AND (pd3.record_type in ('CHCST','ACHCST')
or ( pd3.record_type = 'SAPBA'
and pd3.sub_record_type = 'Chargeback')))
AND pd.commission_header_id = (SELECT MAX(pd4.commission_header_id)
FROM pxmis.pd_commissions pd4
WHERE pd4.application = pd.application
AND pd4.plan = pd.plan
AND pd4.sales_rep_id = pd.sales_rep_id
AND pd4.payroll_num = pd.payroll_num
AND pd4.record_type = pd.record_type)
AND olm.function_type = :10
AND pd.processed_date BETWEEN ADD_MONTHS(:11,(olm.lookback_months_high - 1) * -1) AND ADD_MONTHS(:12, (olm.lookback_months_low - 2) * -1) - 1
AND pd.source = :13
AND pay_freq IS NOT NULL
AND pd.core_conversion_revenue IS NULL;
Sidenote: (Due to my reputation I can not make comments:)
This is my first time answering. Hopefully it will help.
I do not know if it might help, but most of the SQL script (maybe all of it), can be rewritten in other languages. For example you can use JOINS in C# .NET LINQ.
But a way I usually separate the SQL script, is to look for the keywords and see what they do. Do not confuse the big letters from the small ones.
The SELECT function selects all of the datas.
The TO_DATE function says that it will convert the a string to date (source: http://www.techonthenet.com/oracle/functions/to_date.php)
The LEAST function returns the smallest number between the variables you have as parameters (Source: http://www.techonthenet.com/oracle/functions/least.php)
You can do this for every function, and try and grasp what the script does.
I think you could end the script here: FROM pxmis.pd_commissions pd
Also I have seen that you do a JOIN.
Here you could properly make a new script and run that code.
Right now I might not be able to make it more readable. (Mostly because I work with .NET C# linqs).
Again hopefully it helped in some way.

Omit a condition in SQL dynamically

I am developing a website with Asp.net. I have a problem in the following code!
I want to use the DataSqlSource and a attached it to Gridview. I also have a drop down list for categorizing in that page. What i want is, to categorize the Gridview by drop down list. In this case in one condition, a condition must be omitted from the query(Step3_AddArticleType.Status = #Status). For example when the drop down list value is 'All', the mentioned condition must not be counting.
Can any body help me?
I don't know the structure of using that. Here is the code in my DataSqlSource:
SELECT Step3_AddArticleType.ArticleType, Step3_AddArticleType.JournalName, Step5_AddTitle.FullTitle, Step3_AddArticleType.Status, Step3_AddArticleType.ArticleNum,
Step5_AddTitle.ArticleID, Step3_AddArticleType.ID, Step3_AddArticleType.Date, CONVERT(VARCHAR(10), Step3_AddArticleType.Date, 103) AS SubmissionDate
FROM Step3_AddArticleType
INNER JOIN Step5_AddTitle ON Step3_AddArticleType.ArticleID = Step5_AddTitle.ArticleID
WHERE (Step3_AddArticleType.CheckFinish = '0')
AND (Step3_AddArticleType.JournalName = #JournalName)
CASE
WHEN #Status<>'All' THEN
AND (Step3_AddArticleType.Status = #Status)
END
Thank you so much
Your WHERE condition should be like below. Put OR between checking for all and a specific value:
WHERE (Step3_AddArticleType.CheckFinish = '0') AND (Step3_AddArticleType.JournalName = #JournalName)
AND (#Status = 'All' OR Step3_AddArticleType.Status = #Status)

Magento SQL query: Get all simple products that are "not visible individually"

I am looking to write an SQL query directly on the Magento database that gets all Simple products that have the visibility attribute of "not visible individually", for which the value is 1 i believe.
Can anyone help with this? So far I have discovered that the visibility value is set in the table
catalog_product_entity_int
but have been unable to progress further. Thanks
There are many reasons to not do this without the ORM, all of which may (or may not) apply to your needs (store filters, reading data from the correct table, etc). At the very least, you can use the product collection object to build the query which you would run:
$coll = Mage::getModel('catalog/product')->getCollection();
$coll->addAttributeToFilter('visibility' , Mage_Catalog_Model_Product_Visibility::VISIBILITY_NOT_VISIBLE);
echo $coll->getSelect();
The resulting query will look like this:
SELECT `e`.*, IF(at_visibility.value_id > 0, at_visibility.value, at_visibility_default.value) AS `visibility`
FROM `catalog_product_entity` AS `e`
INNER JOIN `catalog_product_entity_int` AS `at_visibility_default`
ON (`at_visibility_default`.`entity_id` = `e`.`entity_id`)
AND (`at_visibility_default`.`attribute_id` = '526')
AND `at_visibility_default`.`store_id` = 0
LEFT JOIN `catalog_product_entity_int` AS `at_visibility` ON (`at_visibility`.`entity_id` = `e`.`entity_id`)
AND (`at_visibility`.`attribute_id` = '526')
AND (`at_visibility`.`store_id` = 1)
WHERE (IF(at_visibility.value_id > 0, at_visibility.value, at_visibility_default.value) = '1')
I hope this might work not tested.
$sql = "SELECT * FROM catalog_product_entity_int WHERE visibility=1";
$connection = Mage::getSingleton('core/resource')->getConnection('core_read');
foreach ($connection->fetchAll($sql) as $arraytest) {
echo $arraytest['name'];
}

Oracle update based on query

I've got the folloing tables:rashodz, naklrashodz, transport, trans_task_load, shipment_plan.
What I need is to update tbl:rashodz.id_ship whith tbl:shipment_plan.id_ship as follows
rashodz.id2 = shipment_plan.id2
and rashodz.nsthet = naklrashodz.nsthet
and naklrashodz.nsthet = trans_task_load.nsthet
and shipment_plan.idts = trans_task_load.idts
Just do not have an idea how to do it.
When there are two tables under consideration there is no problem, but how to do it when multiple tables are involved?
I would appreciate any help.
Is the code snippet you give the condition for the update?
Then how about:
update rashodz r
set id_ship = nvl(
(select id_ship
from shipment_plan,
naklrashodz,
transport,
trans_task_load
where r.id2 = shipment_plan.id2
and r.nsthet = naklrashod.nsthet
and naklrashod.nsthet = trans_task_load.nsthet
and shipment_plan.idts = trans_task_load.idts
), id_ship)
The purpose of the NVL in this case is that if there is no match, id_ship remains unchanged from its original value.